package agentsSME;


import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.logging.Logger;

import otherOrganizations.ServiceCompany;
import au.com.bytecode.opencsv.*;
import enviornment.Clock;
import enviornment.FloodWarning;
import enviornment.Flood;
import main.BuildModel;
import main.Organization;
import repast.simphony.context.Context;
import repast.simphony.engine.environment.RunEnvironment;
import repast.simphony.engine.schedule.IAction;
import repast.simphony.engine.schedule.ISchedule;
import repast.simphony.engine.schedule.ScheduleParameters;
import repast.simphony.engine.schedule.ScheduledMethod;
import repast.simphony.engine.watcher.Watch;
import repast.simphony.engine.watcher.WatcherTriggerSchedule;
import repast.simphony.essentials.RepastEssentials;
import repast.simphony.util.ContextUtils;
/**
 * Creates a Manufacture SME. 
 * @author Chunhui Li
 *
 */
public class ManufactureSME extends SME {
	private static final double aidDays=10.0; 
	private static final double HIGHEST_P=40.0; // highest priority
	private double time;
	
	private LinkedList<Products> products;
	
	private boolean hasElectricityGenerator;
	private int busyEmployees; // in dealing with emergency 
	private int idleEmployees; // in dealing with emergency
	private int msgNumber;

	//private static Logger LOGGER = Logger.getLogger(ManufactureSME.class.getName());
	private BehaviourSME produce;

	private BehaviourSME evacuate;
	private BehaviourSME liftUpITEquipments;
	private BehaviourSME liftUpStock;
	private BehaviourSME engineeringProtection; // seal-doors/pumps/cover things by waterproof bags/cut-off electricity
	private BehaviourSME waitToEvacuate;
	//	private BehaviourSME notReturnToWork;

	private BehaviourSME useElectricityGenerator;
	private BehaviourSME hireElectricityGenerator; //electricity generator/ other equipments
	private BehaviourSME contactElectricians;
	private BehaviourSME waitForElectricians;
	private BehaviourSME restorePower;

	private BehaviourSME contactLandlord;

	private BehaviourSME directLandline;
	private BehaviourSME contactSuppliers;
	private BehaviourSME contactCustomers;

	private BehaviourSME contactInsurer;
	private BehaviourSME sourceMoney;
	private BehaviourSME catalogueDamage;
	private BehaviourSME waitInsurancePayment;

	private BehaviourSME dryMachinary;	
	private BehaviourSME moveStock;
	private BehaviourSME workOnAboveFloors;
	private BehaviourSME cleanUpByEmployees;
	private BehaviourSME contactContractors;
	private BehaviourSME waitContractors;
	private BehaviourSME cleanUpByContractors;

	private BehaviourSME backToOperation;
	private BehaviourSME workWithAid;
	private BehaviourSME requestAid;

	private BehaviourSME notAtWork;

	private LinkedList<BehaviourSME> behaviours;
	private Random random;
	private boolean simulation_stop;// this SME finishes the simulated actions

	private boolean inResetting;// reset employees status during the simulation 
	private boolean isFloodedInNight;
	private Clock startResponse;
	private Clock startRecovery;
	private boolean receivedWarningSave;

	private boolean hasCashNow;
	private LinkedList<ServiceCompany> comingServiceCom;
	private int employeesAvailableInPremises; // for work
	private int employeesForAid;
	private double totalMachines;
	private double availableMachinesInPremises;
	private double availableMachinesMutualAid;
	private double productionLevel; // in percentage
	private LinkedList<Double> productionLevelRecord;
	private LinkedList<Double> stockLevelRecord;
	private LinkedList<Double> stockGroundRecord;
	private LinkedList<Double> stockAboveGroundRecord;
	private LinkedList<Double> availableStockRecord;
	private LinkedList<Double> availableMachinesRecord;
	private LinkedList<Integer> availableEmployeeInPremisesRecord;
	private LinkedList<Integer> availableEmployeeInAidRecord;
	
	/**
	 * The constructor of a manufacture SME agent.
	 */
	public ManufactureSME() {
		super();
		this.setSector("Manufacturing");
		random = new Random();
		
		this.setStock(new Stock(60.0,0.5,0.5));// stock units, ration of gound location, ratio of fragile stock		
		regularStock=stock.getStockLevel();
		products= new LinkedList<Products>();
		productionLevel = 100;
		time = 0;
		busyEmployees =0;
		idleEmployees = numberEmployees;	
		simulation_stop = false;
		hasElectricityGenerator = false;//random.nextBoolean()	
		startRecovery=new Clock();
		inResetting = false;
		isFloodedInNight=false;
		startResponse=new Clock();		
		receivedWarningSave=false;
		hasCashNow=false;
		msgNumber=0;
		comingServiceCom=new LinkedList<ServiceCompany>();
		employeesAvailableInPremises=numberEmployees;
		employeesForAid=0;
		totalMachines=100.0;
		availableMachinesInPremises = totalMachines;
		availableMachinesMutualAid=0.0;
		productionLevel=100.0;
		productionLevelRecord=new LinkedList<Double>();
		stockLevelRecord=new LinkedList<Double>();
		stockGroundRecord=new LinkedList<Double>();
		stockAboveGroundRecord=new LinkedList<Double>();
		availableMachinesRecord=new LinkedList<Double>();
		availableEmployeeInPremisesRecord=new LinkedList<Integer>();
		availableEmployeeInAidRecord=new LinkedList<Integer>();
		availableStockRecord=new LinkedList<Double>();
	}
	
	public void updateAvailableEmployees(){
		if(!this.isFlooded){
			employeesAvailableInPremises=numberEmployees;
			if(liftUpITEquipments.isInProgress()||engineeringProtection.isInProgress()||liftUpStock.isInProgress()){
				employeesAvailableInPremises=produce.getResources();
			}
			if(liftUpStock.isDone() && liftUpITEquipments.isDone()&&engineeringProtection.isDone() && !produce.isInProgress()){
				employeesAvailableInPremises=0;
			}
			/*
			if(!liftUpITEquipments.isInProgress()&&!engineeringProtection.isInProgress()&&!liftUpStock.isInProgress()&&!liftUpStock.isDone()
					&&!liftUpITEquipments.isDone()&&!engineeringProtection.isDone() && !produce.isInProgress()){
				employeesAvailableInPremises=0;
			}*/
			
			/*
			 * 
			 * Here should update the figures when the sme privodes aid to its partners
			 */
		}else{
			if(evacuate.isInProgress()){
				employeesAvailableInPremises=0;
			}
			if(backToOperation.isInProgress()){// &&!backToOperation.isPaused()){
				employeesAvailableInPremises=backToOperation.getResources();
			}else{
				employeesAvailableInPremises=0;
			}
			
			if(workWithAid.isInProgress()){
				employeesForAid=workWithAid.getResources();		
			}else{
				employeesForAid=0;
			}
			
		}
		availableEmployeeInPremisesRecord.add(employeesAvailableInPremises);
		availableEmployeeInAidRecord.add(employeesForAid);
	}
		
	public double ratioAvailableMachinesInToTotal(){
		double d=availableMachinesInPremises/totalMachines;
		return d;
	}
	public double ratioAvailableEmployeesInToTotal(){
		double d= employeesAvailableInPremises*100/this.getSize();	
		return d;
	}
	public void getProductionLevel(){
		double d=ratioAvailableEmployeesInToTotal()*ratioAvailableMachinesInToTotal()+availableMachinesMutualAid;	
		if(stock.getStockLevel()>=1.0){
			productionLevelRecord.add(d);
		}
		if(stock.getStockLevel()<1.0){
			if(stock.getStockLevel()>=d/100.0 && d/100.0>0.0){			
				productionLevelRecord.add(d);
			} 
			if(stock.getStockLevel()<d/100.0 && stock.getStockLevel()>0.0){
				productionLevelRecord.add(stock.getStockLevel()*100.0); //limited by stock
			}
			else { //when stock level is 0			
				productionLevelRecord.add(0.0);
			}
		}
		
	//	return d;
	}
	public void reducedAvailableMachines(double x){
		if(x<=availableMachinesInPremises){
			availableMachinesInPremises=availableMachinesInPremises-x;
		}else{
			availableMachinesInPremises=0;
		}
	}
	public void updateAvailableMachines(){
		double d=0.0;
		if(dryMachinary.isInProgress() &&availableMachinesInPremises<=100.0){
	//		if(availableMachinesInPremises>0.0){
				availableMachinesInPremises=availableMachinesInPremises+(1.0*totalMachines/dryMachinary.getDuration());
	//		}
			/*
			if(availableMachinesInPremises==0.0){
				availableMachinesInPremises=1.0;
			}*/
		}
		if(dryMachinary.isDone()){
			availableMachinesInPremises=100.0;
		}
		if(workWithAid.isDone()){
			availableMachinesMutualAid=0;
		}
		d=availableMachinesInPremises+availableMachinesMutualAid;
		availableMachinesRecord.add(d);
	}

	public BehaviourSME getBehaviour (String s){
		BehaviourSME b = new BehaviourSME (this," ", 10, 100, false,0, " ",true);
		for (int i=0; i<behaviours.size(); i++){
			if(s.equals(behaviours.get(i).getBehaviourName())){
				b=behaviours.get(i);
				b.setCode(behaviours.get(i).getCode());
			} 
		}
		return b;
	}
	public void setSMEFloodInNight(boolean b){
		isFloodedInNight=b;
	}
	public boolean getFloodedInNight(){
		return isFloodedInNight;
	}
	public void setSimStop(boolean b){
		simulation_stop = b;
	}
	
	public void setStartRecovery(Clock c){
		startRecovery=c;
	}
	public Clock getStartRecovery(){
		return startRecovery;
	}
	public boolean getInResetting(){
		return inResetting;
	}
	public void setInResetting(boolean b){
		inResetting = b;
	}
	
	public void setStartResponse(Clock c){
		startResponse=c;
	}
	public Clock getStartResponse(){
		return startResponse;
	}
	public LinkedList<Products> getProducts(){
		return products;
	}
	public boolean getHasEGenerator(){
		return hasElectricityGenerator;
	}
	public void setHasEGenerator(boolean b){
		hasElectricityGenerator = b;
	}

	/**
	 * This method defines SMEs subscribe weather report from Met Office.
	 */
	public void subscribeMetOffice(){

	}
	public void setNightFlood(){
		for (Flood f: BuildModel.floodContext){
			if(f.getID().equals(this.getSerialNo())){
				setSMEFloodInNight(f.getNightFlood());
				startResponse=f.getStartFlood();
				startRecovery=f.getFinishFlood();
			}
		}

	}

	/**
	 * Simulates that the SME perceives danger by seeing the water level increases at the door step.
	 */
	//@Watch(watcheeClassName="enviornment.Flood", 
	//		whenToTrigger = WatcherTriggerSchedule.IMMEDIATE, watcheeFieldNames = "becomeDangerous")	
	//@ScheduledMethod(duration = 1)	
	public void perceiveDanger(){
		for (Flood f: BuildModel.floodContext){
			/*
			if(f.getID().equals(this.getSerialNo())&& this.hasBundWall){
				if(f.getInundationLevel()<1.0){
					f.setInundationLevel(0.0);
				}
			}*/
			if(f.getID().equals(this.getSerialNo())&& (f.getInundationLevel()> 0.0||f.getRoadWater()>0.0)){
				setPerceived(true);
				System.out.println("!!!!"+this.companyName+" perceived DANGER! " + " at time: " + time);		
			}
			if(f.getID().equals(this.getSerialNo())){
				if(f.getInundationLevel()> 0.0){
					this.setFlooded(true);
				}
				if(f.getInundationLevel()> 0.0 && f.getInundationLevel()<= 0.2){
					if(availableMachinesInPremises>90.0){
						availableMachinesInPremises=90.0;						
					}
					
				}
				if(f.getInundationLevel()> 0.2 && f.getInundationLevel()<= 0.5){
					if(availableMachinesInPremises>50.0){
						availableMachinesInPremises=50.0;
					}
				}
				if(f.getInundationLevel()> 0.0 && f.getInundationLevel()<= 0.5){
					stock.setStockLevel(stock.getStockUnitsAboveGround());
					stock.setStockUnitsGround(0.0);
				}
				if(f.getInundationLevel()> 0.5){
					if(availableMachinesInPremises>0.0){
						availableMachinesInPremises=0;
					}
					stock.setStockLevel(0.0);
					stock.setStockUnitsAboveGround(0.0);
					stock.setStockUnitsGround(0.0);
				}
				this.waterHistory.add(f.getInundationLevel());
			}
		}
		// when the premises is not flooded and when it is work time, check neighbours. Neighbours' conditions mean warnings for the SME itself
		if(!perceivedDanger && clock.getHour()>=BuildModel.START_WORK_HOUR && clock.getHour() < BuildModel.END_WORK_HOUR ){
			LinkedList<SME> neighbours = this.getNeighbours();
			for(SME sme: neighbours){
				for (Flood f: BuildModel.floodContext){
					if(f.getID().equals(sme.getSerialNo()) && (f.getInundationLevel()> 0.0||f.getRoadWater()>0.0)){
						//setPerceived(true);
						receiveWarning=true;
						receivedWarningSave = true;
						System.out.println("!!!!"+this.companyName+" perceived DANGER! from its neighbours" + " at time: " + time);
					}
				}
			}
		}
	}
	/**
	 * Sets the number of busy employees	
	 * @param x the number of allocated employees to a behaviour
	 */

	public void moreBusyEmployees (int x){
		busyEmployees = busyEmployees + x;
		idleEmployees = employeesAtWork - busyEmployees;
	}

	public void freeEmployees (int x){
		busyEmployees = busyEmployees -x;
		idleEmployees = employeesAtWork - busyEmployees;
	}

	/**
	 * Schedules an action (i.e., a behaviour)
	 * @param action the behaviour
	 * @param start the start tick
	 * @param allocatedEmployees the resources allocated to perform the behaviour
	 */
	public void scheduleAction(BehaviourSME action, double start, int allocatedEmployees){

		System.out.println(this.companyName+ " sechedule action:"+action.getBehaviourName()+" people:" +allocatedEmployees
				+ ". Currently busyEmployees: "+ busyEmployees 
				+ " idleEmployees: "+idleEmployees +
				" Total Number of Employees: "+numberEmployees + " Employees at work: "+ employeesAtWork);
		//for contiuing the paused behaviour
		if(action.isPaused()){
			action.setPause(false);
		}

		ISchedule schedule = RunEnvironment.getInstance().getCurrentSchedule();
		ScheduleParameters params = ScheduleParameters.createOneTime(start,action.getPriority());			
		schedule.schedule(params, action);		
		if (allocatedEmployees > employeesAtWork){
			System.out.println("Error! not enough people can meet the resource requirement");
			allocatedEmployees=employeesAtWork;
		}
		action.setResources(allocatedEmployees);		
		action.setStartTime(start);
		action.setExecutionT(start);
		action.setDuration(calcDuration(action));// in the calculation of durations, the resource will be reset if there are too many resources
		//allocated
		//action.setEndTime(start+action.getDuration());//....................
		allocateEmployees(action, action.getResources());// allocate the actual number of people to work on the task
		moreBusyEmployees(action.getResources()); //update the busy and idle number of employees

	}
	public void scheduleWait(BehaviourSME action, double start, double duration){
		System.out.println(this.companyName+ "sechedule action:"+action.getBehaviourName());
		ISchedule schedule = RunEnvironment.getInstance().getCurrentSchedule();
		ScheduleParameters params = ScheduleParameters.createOneTime(start,action.getPriority());			
		schedule.schedule(params, action);			
		action.setStartTime(start);
		action.setExecutionT(start);
		action.setDuration(duration);
		action.setEndTime(start+duration);
	}

	public void reallocateResources(){
		ArrayList <BehaviourSME> list = new ArrayList<BehaviourSME>();
		ArrayList<BehaviourSME> sortedList = new ArrayList<BehaviourSME>();
		for (BehaviourSME b: behaviours){
			if(b.isInProgress() && b.getShared() && !b.getBehaviourName().contains("wait")){
				list.add(b);
			}
		}
		if(backToOperation.isInProgress()&&list.size()>1){
			list.remove(backToOperation);
			emergencyStop(backToOperation);
	//		backToOperation.setResources(0);
			backToOperation.setDone(false);
		}
		if(idleEmployees>0 && list.size()>0){			
			//find the ongoing behaviour with the highest priority
			while(list.size()>0){
				double highest =list.get(0).getPriority();
				BehaviourSME b = list.get(0);
				for(int i=1;i<list.size();i++){
					double temp = list.get(i).getPriority();
					if(temp>highest){
						highest = temp;
						b=list.get(i);					
					}	
				}
				sortedList.add(b);
				list.remove(b);
			}

			while(idleEmployees>0 && sortedList.size()>0){
				BehaviourSME sorted = sortedList.get(0);				
				double task = sorted.remainTask(time);
				//reset the task;
				if(task>(sorted.getResources()*1.0)){
					sorted.setTask(task);
					if(Math.floor(task/(sorted.getResources()+idleEmployees))>=1.0){
						reschedule(sorted,time,idleEmployees);
					}else{
						reschedule(sorted, time, (int)(task-sorted.getResources()));
					}
					System.out.println(this.getName()+" reschedule "+ sorted.toString()+"; resource= "+sorted.getResources());
					sortedList.remove(sorted);
				}else{
					sortedList.remove(sorted);
				}
			}
			if(idleEmployees>0 && !backToOperation.isInProgress()){
				scheduleAction(backToOperation, time, idleEmployees);
			}			
		}	
	}
	public void reschedule(BehaviourSME action, double start, int add){
		if(idleEmployees >= add){			
			//reset the allocated resources
			action.setExecutionT(start);
			action.setResources(action.getResources()+add);			
			//reset the duration: the time that has been used to perform this behaviour plus the duration of the left task with more resources
			//action.setDuration(time-action.getExecutedTime()+calcDuration(action));
			action.setDuration(calcDuration(action)); //new duration
			action.setEndTime(start+action.getDuration());
			ISchedule schedule = RunEnvironment.getInstance().getCurrentSchedule();
			ScheduleParameters params = ScheduleParameters.createOneTime(start,action.getPriority());			
			schedule.schedule(params, action);			
			allocateEmployees(action, add);
			//trial
			//action.setEndTime(start+action.getDuration());//.............................
			moreBusyEmployees(add);			

		}
	}

	/**
	 * Calculates duration of each behaviour based the task of the behaviour and
	 *  the employees busy with the task. 
	 * @param b behaviour
	 * @return duration
	 */
	public double calcDuration(BehaviourSME b){
		//to make sure each employee work on the task for at least 1 tick
		if(b.getTask()/b.getResources()<1.0){
			b.setResources((int)b.getTask());

		}
		double duration= Math.floor(b.getTask()/b.getResources());
		double work = duration/BuildModel.TICK_PER_HOUR;
		b.setHoursOfWork(work);
		if(b.isEmergent()){
			return duration;
		}
		else{
			Clock timer = new Clock();
			//covert duration ticks to working hours. for example, 15 ticks duration time would be 1 day 5 hours work if working hours are 10 per day.
			timer = timer.workingHours(duration, BuildModel.WORKINGHOURS); 
			Clock c = new Clock();
			double start_tick = b.getExecutedTime();
			c = c.convertTicks(start_tick);

			timer.addWorkingTime(c);
			/*
			if(timer.getHour()==BuildModel.END_WORK_HOUR){
				if(timer.getMin()>0){
					timer.setHour(BuildModel.START_WORK_HOUR);
					timer.setDay(timer.getDay()+1);
				}
			}
			 */
			if(timer.getHour()>BuildModel.END_WORK_HOUR){				
				int x = timer.getHour()-BuildModel.END_WORK_HOUR;
				timer.setHour(BuildModel.START_WORK_HOUR+x);
				timer.setDay(timer.getDay()+1);
				if(x> BuildModel.END_WORK_HOUR){
					timer.setHour(x- BuildModel.END_WORK_HOUR+BuildModel.START_WORK_HOUR);
					timer.setDay(timer.getDay()+1);
				}
			}
			if(timer.getHour()< BuildModel.START_WORK_HOUR){
				int x = timer.getHour()+BuildModel.START_WORK_HOUR;
				timer.setHour(x);
				if(x>BuildModel.END_WORK_HOUR){
					timer.setHour(BuildModel.START_WORK_HOUR+x-BuildModel.END_WORK_HOUR);
					timer.setDay(timer.getDay()+1);
				}

			}
			double newDuration = timer.convertClock()- start_tick ;
//			System.out.println(b.getBehaviourName()+" AT Tick "+ time+ ": Duration:"+ duration+ " = "+b.getTask() + " / "+ b.getResources()+ " START AT "+start_tick+" "+ c.toString()+"; END AT " +timer.convertClock()+" "+ timer.toString()
//					+"the newly coverted time ticks for duration is "+newDuration );
			return newDuration;
		}
	}
	/**
	 * Stop a behaviour without rescheduling the unfinished work.
	 * @param b
	 */
	public void emergencyStop(BehaviourSME b){
		b.setDone(true);
		b.setProgress(false);
		if(clock.getHour()<BuildModel.START_WORK_HOUR || clock.getHour() >= BuildModel.END_WORK_HOUR){
			Clock c = new Clock();
			c.setDay(clock.getDay());
			c.setHour(BuildModel.END_WORK_HOUR);
			b.setEndTime(c.convertClock());
		}else{
			b.setEndTime(time); //....................................
		}
		//Update employees record
		releaseEmployees(b);
		//update numbers of busy and idle employees
		freeEmployees(b.getResources());
	}

	/**
	 * Terminate a behaviour and if there is remaining task, reschedule the remaining part to available 
	 * employees.
	 * @param b behaviour of SME
	 */
	public void terminateBehaviour(BehaviourSME b){		
		b.setDone(true);
		b.setProgress(false);
		b.setEndTime(time); //....................................
		//Update employees record
		releaseEmployees(b);
		//update numbers of busy and idle employees
		freeEmployees(b.getResources());
		double remainder = b.getTask()-(b.getHourOfWork() *b.getResources()*BuildModel.TICK_PER_HOUR);
		if(remainder>=1.0){
			b.setTask(remainder);
			b.setProgress(true);
			b.setDone(false);
			if(idleEmployees>= remainder){			
				scheduleAction(b,time,(int)remainder);
			} else{
				scheduleAction(b,time,idleEmployees);
			}
		}
	}
	public void pauseBehaviour(BehaviourSME b){		
		if(b.isInProgress()){
			b.setDone(false);
			b.setProgress(false);
			b.setPause(true);
			b.setEndTime(time); //....................................
			//Update employees record
			releaseEmployees(b);
			//update numbers of busy and idle employees
			freeEmployees(b.getResources());
			Clock c1=new Clock();
			c1.convertTicks(b.getExecutedTime());
			Clock c2 = this.clock;
			double workedhours= c1.workingHoursBetweenTwo(c1, c2);
			double remainder = b.getTask()-(workedhours*BuildModel.TICK_PER_HOUR);
			b.setTask(remainder);
			System.out.println(b.getBehaviourName()+"      is paused");
			updateEmployees();
		}
	}
	/**
	 * terminate behaviours of waiting type
	 * @param b the behaviour of SME
	 */
	public void terminateWait(BehaviourSME b){
		b.setDone(true);
		b.setProgress(false);
		b.setEndTime(time); //................................
	}
	/**
	 * Updates number of employees in different status in every tick: check whether a behaviour is in process, if it is in process,
	 * reduce the number of allocated employees in idleEmployees and update the number of busyEmployees.
	 */
	public void updateEmployees(){
		idleEmployees = employeesAtWork;
		for (BehaviourSME b: behaviours){
			if (b.isInProgress()){
				//calculate the loss caused by unfinished rescue work.
				idleEmployees = idleEmployees - b.getResources();
				busyEmployees = employeesAtWork - idleEmployees;
			}
		}
	}

	/**
	 * Stop all ongoing behaviours.
	 */
	public void stopAllBehaviours(){
		for (BehaviourSME b: behaviours){			
			if (b.isInProgress() && !b.getBehaviourName().equals("evacuation")){
				//calculate the loss caused by unfinished rescue work.
				if(b.getBehaviourName().contains("wait")){
					terminateWait(b);
				}
				else{
					b.setDone(true);
					b.setProgress(false);
					b.setEndTime(time);			
					//Update employees record
					releaseEmployees(b);
					//update numbers of busy and idle employees
					freeEmployees(b.getResources());
					//backToOperation.setResources(0);
					b.setResources(0);
				}
			}
		}
	}
	/*
	@ScheduledMethod(start = 481, interval = 240, priority =15)
	public void replenishStock(){
		stock.setStockLevel(stock.getStockLevel()+regularStock);
		stock.setStockUnitsAboveGround(stock.getStockUnitsAboveGround()+regularStock*(1.0-stock.getRatioLocation()));
		stock.setStockUnitsGround(stock.getStockUnitsGround()+regularStock*stock.getRatioLocation());
	}
*/
	/**
	 * Updates the agent in every step. Behaviour rules are implemented here.
	 */
	@Override
	@ScheduledMethod(start =1, interval = 1, priority =10)
	public void step() {
		time = RepastEssentials.GetTickCount();		
		if(time==1.0){				
			employeesAtWork=numberEmployees;
			idleEmployees = employeesAtWork;
			initialiseBehaviours();
			setNightFlood();
		}
		clock.convertTicks(time);
//		System.out.println("CLOCK: "+ clock.getDay() +" Day "+ clock.getHour() + " Hour"+ clock.getMin() +" Minute");
		updateEmployees();
		//		System.out.println("Update the employee status:"+this.companyName+ "busyEmployees: "+ busyEmployees + "; idleemployees: "+idleEmployees +
		//				"; Total Number of Employees: "+numberEmployees );
		updateAvailableEmployees();
		updateAvailableMachines();				
		getProductionLevel();
		
		updateReceiver();		
		perceiveDanger();	
		endBehaviours();
		
		stockLevelRecord.add(stock.getStockLevel());
		stockGroundRecord.add(stock.getStockUnitsGround());
		stockAboveGroundRecord.add(stock.getStockUnitsAboveGround());
		availableStockRecord.add(stock.getStockLevel()*100.0/regularStock);
		if(clock.getHour()>= BuildModel.START_WORK_HOUR  && clock.getHour() < BuildModel.END_WORK_HOUR ){
			if(produce.isInProgress() && stock.getStockLevel()>=1.0){
				/*
				stock.setStockLevel(stock.getStockLevel()-1.0);
				if(random.nextInt(2)==0 && stock.getStockUnitsGround()>=1.0){
					stock.setStockUnitsGround(stock.getStockUnitsGround()-1.0);
				}else{
					stock.setStockUnitsAboveGround(stock.getStockUnitsAboveGround()-1.0);
				}*/
				stock.useStock(1.0);
			}
			double x=productionLevelRecord.getLast()/100.0;
			if(backToOperation.isInProgress() && productionLevelRecord.getLast()>0.0 && stock.getStockLevel()>=x){
				stock.useStock(x);
			}
		}
		if(liftUpStock.isInProgress()){
			if(stock.getStockUnitsGround()>=2.0){
				stock.setStockUnitsAboveGround(stock.getStockUnitsAboveGround()+2.0); //Here needs another assumption
				stock.setStockUnitsGround(stock.getStockUnitsGround()-2.0);
			}else{
				stock.setStockUnitsAboveGround(stock.getStockLevel()); //Here needs another assumption
				stock.setStockUnitsGround(0.0);
			}
		}
		/*
		stockLevelRecord.add(stock.getStockLevel());
		stockGroundRecord.add(stock.getStockUnitsGround());
		stockAboveGroundRecord.add(stock.getStockUnitsAboveGround());
		availableStockRecord.add(stock.getStockLevel()*100.0/regularStock);
		*/
		if(clock.getHour()>= BuildModel.START_WORK_HOUR && clock.getHour() <= BuildModel.END_WORK_HOUR){
			if(perceivedDanger && !isFloodedInNight){
				if(!evacuate.isInProgress() && !evacuate.isDone()){				
					//if employees are busy with any behaviour (excluding evacuation), 
					//finish lift-up immediately and start evacuation.			
					stopAllBehaviours();		
					// schedule all employees to evacuate. This includes getting rescued.
					scheduleAction(evacuate, time, employeesAtWork);				
				}
			}
			if(perceivedDanger && isFloodedInNight){
				if(!evacuate.isInProgress() && !evacuate.isDone()){				
					//if employees are busy with any behaviour (excluding evacuation), 
					//finish lift-up immediately and start evacuation.			
					stopAllBehaviours();		
					// No evacuation happens because nobody is in the premises
					evacuate.setDone(true);
				}
			}
		}
		/*
		 * Lift-up is carried out by all employees when a SME receives the warning before floods start.
		 * This is executed when the SME hasn't perceive any danger, but has received warnings from
		 * government bodies.
		 */
		if(!perceivedDanger&& clock.getHour()>= BuildModel.START_WORK_HOUR  && clock.getHour() <= BuildModel.END_WORK_HOUR ){
			if(receiveWarning && trustEA){
				//				double t = Math.round(cleanUpByEmployees.getTask() * (1.0-cleanUpByEmployees.getImpactFactor()));
				//				cleanUpByEmployees.setTask(t);
				if(!liftUpITEquipments.isDone() && !liftUpITEquipments.isInProgress()){
					if(produce.isInProgress()){
						emergencyStop(produce);
						produce.setResources(0);
						scheduleAction(liftUpITEquipments, time, idleEmployees);
						
					}else{
						scheduleAction(liftUpITEquipments, time, idleEmployees);
					}
				}
			}			
		}
		/*
		 * Using engineering materials to protect property is schedule to be done after lift-up is finished.
		 * Because this behaviour is a reaction to emergency(i.e., flood), it is not restricted by whether it is working hours currently.
		 */
		if((liftUpITEquipments.isDone()||liftUpITEquipments.isInProgress())&&idleEmployees>0 && this.getHasEngineers() 
				&& !engineeringProtection.isDone() && !engineeringProtection.isInProgress()){
			//				int e = (int) Math.round(numberEmployees*0.5); // the number of engineers who know how to seal the building
			if((double)idleEmployees<engineeringProtection.getTask()){
				scheduleAction(engineeringProtection, time, idleEmployees);
			}else{
				scheduleAction(engineeringProtection, time, (int)engineeringProtection.getTask());
			}
		}
		if((engineeringProtection.isDone()||engineeringProtection.isInProgress())&&idleEmployees>0 
				&&!liftUpStock.isInProgress()&&!liftUpStock.isDone()){
			scheduleAction(liftUpStock, time, idleEmployees);
		
		}
		
		
		/*
		 * This is regular daily production of a manufacture SME. This gets executed when the SME 
		 * hasn't perceived any danger and hasn't received any warning from government bodies.
		 */
		if(!perceivedDanger && !isFlooded){// !evacuate.isDone() && !evacuate.isInProgress() ){
			// At working hours 9 - 17, everything is normal, start producing products.			 
			if(clock.getHour()>= BuildModel.START_WORK_HOUR  && clock.getHour() <BuildModel.END_WORK_HOUR ){
				if(!receiveWarning){ 
					if(!produce.isInProgress()&&idleEmployees>0){
						scheduleAction(produce, time, idleEmployees);	
					}
					/*
					 * If weather is continuously bad, talk to neighbours.
					 * If any neighbour receives warning, start to lift up things. 
					 */
					for (int i=0; i<this.getNeighbours().size(); i++){
						if(this.getNeighbours().get(i).receivedWarning()){
							this.setReceiveWarning(true);
						}
					}
				}											
			}		
		}
		
		/*
		 *Aftermath phase. 
		 */
		if(!perceivedDanger && evacuate.isDone()){// && !fullyRecovered){
			if(isFlooded){
				if(clock.getHour()>=BuildModel.START_WORK_HOUR && clock.getHour() < BuildModel.END_WORK_HOUR ){				
					aftermathBehaviours(); 					
				}
			}
		}

		if(clock.getHour()>=BuildModel.START_WORK_HOUR && clock.getHour() < BuildModel.END_WORK_HOUR){
			reallocateResources();		
		}
		
		turnOnStop();
		/*
		if(this.getFlooded() && cleanUpByContractors.isDone()){
			turnOnStop();	
		}
		
	*/
		
		// reset these two status in each step
		receiveWarning = false;
		perceivedDanger = false;

		if(BuildModel.FORCE_STOP){
			stopAtATick(BuildModel.FORCE_STOP_TICK);
		}
		if(!BuildModel.FORCE_STOP){ 
			if(simulation_stop){
				stop();
			}
			else{
				Context c = ContextUtils.getContext(this);
				if (c.size()<BuildModel.number_smes && c.size()>1&& produce.isInProgress()){
					stopAllBehaviours();
					stop();
				}
			}
		}
		
	}
	
	public void requestAid(){
		if(this.participateMutualAid && !requestAid.isInProgress()&& !requestAid.isDone() && idleEmployees>0){
			scheduleAction(requestAid,time,1);
			
		}
	}
		
	public void aftermathBehaviours(){
		if(idleEmployees>=numberVacancy && !notAtWork.isInProgress() && !notAtWork.isDone()){						
			scheduleAction(notAtWork, time, numberVacancy);						
		}
		requestAid();
		if(idleEmployees>0 && !directLandline.isInProgress() && !directLandline.isDone()){
			scheduleAction(directLandline, time, 1);
		}
		if(!cashAvailableForRecovery && !sourceMoney.isInProgress() && !sourceMoney.isDone() && idleEmployees>0){
			scheduleAction(sourceMoney, time, 1);
		}

		// Electricity part			
		if(!powerOn){
			if (this.hasElectrician){ // Or has premier relationships
				if(idleEmployees >0 && !contactElectricians.isDone() && !contactElectricians.isInProgress()){
					scheduleAction(contactElectricians, time, 1);
				}
				if(contactElectricians.isDone() && !restorePower.isDone() && !restorePower.isInProgress()&& idleEmployees >0){
					scheduleAction(restorePower, time, 1); // not done by employees; has to be re-written.
				}
			}

			if(!this.hasElectrician){
				if(idleEmployees >0 && !contactElectricians.isDone() && !contactElectricians.isInProgress()){
					scheduleAction(contactElectricians, time, 1);
				}
				if(contactElectricians.isDone() && !waitForElectricians.isDone() && !waitForElectricians.isInProgress()&& idleEmployees >0 ){
					scheduleWait(waitForElectricians, time, waitForElectricians.getTask()); //wait behaviours have to be re-written.
				}
				if(waitForElectricians.isDone() && !restorePower.isDone() && !restorePower.isInProgress()&& idleEmployees >0){
					scheduleAction(restorePower, time, 1); // not done by employees; has to be re-written.
				}						
			}	

			//add whether they have good contacts later.
			if (this.hasElectricityGenerator && idleEmployees >0 && !useElectricityGenerator.isInProgress() && !useElectricityGenerator.isDone() ){
				scheduleAction(useElectricityGenerator, time, idleEmployees);
				if(useElectricityGenerator.isInProgress()){
					setPowerOn(true);
				}
			}
			if(!this.hasElectricityGenerator && idleEmployees >0){
				if(!hireElectricityGenerator.isDone() && !hireElectricityGenerator.isInProgress() ){
					scheduleAction(hireElectricityGenerator, time, 1); // Do we add "wait"???????
				}
				if(hireElectricityGenerator.isDone()){
					scheduleAction(useElectricityGenerator, time, idleEmployees);
					if(useElectricityGenerator.isInProgress()){
						setPowerOn(true);
					}
				}
			}

		}

		if(powerOn){
			if (cashAvailableForRecovery||hasCashNow){ //What does cash-available influence on??? 
				prepareToRecover();							
			}
			if(!moveStock.isInProgress() && !moveStock.isDone() && idleEmployees>0){
				scheduleAction(moveStock, time, 1);					
			}
			// Arrange working on above floors
			if(!workOnAboveFloors.isInProgress() && !workOnAboveFloors.isDone()&& this.getPremise().getNumberOfFloors()>1&&idleEmployees >0){
				scheduleAction(workOnAboveFloors, time, 1);
			}
			
		} 

		if (coveredByInsurance){
			if(!contactInsurer.isInProgress()&& !contactInsurer.isDone() &&idleEmployees>0){								
				scheduleAction(contactInsurer, time, 1);	
			}
			if(idleEmployees>0 && !catalogueDamage.isInProgress() && !catalogueDamage.isDone()){
				scheduleAction(catalogueDamage, time, 1);
			}
			if(waitInsurancePayment.isInProgress() && !waitInsurancePayment.isDone()){
				scheduleWait(waitInsurancePayment, time, waitInsurancePayment.getTask());
			}
		}		

		// contact landlord, suppliers and customers
		if(directLandline.isDone()){					
			if(idleEmployees>0 && !contactCustomers.isDone()&& !contactCustomers.isInProgress()){
				scheduleAction(contactCustomers, time, 1);                       
			}
			if(idleEmployees>0 && !contactSuppliers.isDone()&& !contactSuppliers.isInProgress()){
				scheduleAction(contactSuppliers, time, 1);   
			}
			if (!ownership && idleEmployees> 0 && !contactLandlord.isInProgress() && !contactLandlord.isDone()){
				scheduleAction(contactLandlord, time, 1);
			}
		}
		backToNormal();//                
	}
	/**
	 * This condition is to make sure the recording ends with back to operation
	 */
	private void turnOnStop(){
		if( backToOperation.getResources()==employeesAtWork && time>backToOperation.getExecutedTime()){// backToOperation.isInProgress() ||
			
			if(this.isFlooded){
				if((!cleanUpByEmployees.isDone()&&!cleanUpByEmployees.isInProgress()) && (!cleanUpByContractors.isDone() &&!cleanUpByContractors.isInProgress())){
					emergencyStop(backToOperation);
					backToOperation.setResources(0);
					scheduleAction(cleanUpByEmployees, time, idleEmployees);
				}
				
			}
			//check if any other behaviour is ongoing	
			if(backToOperation.isInProgress()){
				ArrayList <BehaviourSME> list = new ArrayList<BehaviourSME>();		
				for (BehaviourSME b: behaviours){
					if(b.isInProgress()){
						list.add(b);
					}
				} 
				if(list.size()<=1&&stock.getStockLevel()>0.0){
					getProductionLevel();
					emergencyStop(backToOperation);
//					backToOperation.setResources(0);
					simulation_stop = true;
				}
			}
			
		}
	}
	@SuppressWarnings("rawtypes")
	private void stop(){
	//	getSender().sendMsgToService("Stop", this.GetServiceCompanyList().get(0));
		//		saveData();
		saveDataTimeline();
		saveDataSecond();
		saveEmployeesData();		
		// printEmployeeStatus();
		Context c = ContextUtils.getContext(this);
		if(c.size()>1){
			c.remove(this);
		} 
		else{
			for(ServiceCompany s: this.GetServiceCompanyList()	){
				s.prepareToStop(time);
				s.saveData();
				s.printServiceRecord();
			}
			RunEnvironment.getInstance().endRun();
			
		}

	}
	private void stopAtATick(double tick){
		if(time>=tick){
//			getSender().sendMsgToService("Stop", this.GetServiceCompanyList().get(0));
			this.stopAllBehaviours();
			saveDataTimeline();
			saveDataSecond();
			saveEmployeesData();		
			//			printEmployeeStatus();
			//			RunEnvironment.getInstance().endRun();
			Context c = ContextUtils.getContext(this);
			if(c.size()>1){
				c.remove(this);
			} 
			else{				
				RunEnvironment.getInstance().endRun();
			}
		}

	}
	private void backToNormal(){
		if(!backToOperation.isDone()&&!backToOperation.isInProgress()&& idleEmployees>0){			
			scheduleAction(backToOperation, time, idleEmployees);  
			
		}
	}
	private void prepareToRecover(){
		if(clock.getHour()>=BuildModel.START_WORK_HOUR && clock.getHour() < BuildModel.END_WORK_HOUR){
			if(this.hasGoodWorkSpirit && this.getSize()>2){			
				if (!cleanUpByEmployees.isDone() && !cleanUpByEmployees.isInProgress()&& idleEmployees>1){
					scheduleAction(cleanUpByEmployees, time, idleEmployees-1);
				}
			}
			if(!this.hasGoodWorkSpirit||this.getSize()<3){
				if(!contactContractors.isDone() && !contactContractors.isInProgress() && idleEmployees >0){
					scheduleAction(contactContractors, time, 1);
				}
				//	if(contactContractors.isDone() && !waitContractors.isInProgress() && !waitContractors.isDone()){
				//	scheduleWait(waitContractors, time, (double)random.nextInt(BuildModel.TICK_PER_HOUR*10+72));
				//}
				/*
				if (contactContractors.isDone() && !cleanUpByContractors.isDone() && !cleanUpByContractors.isInProgress()&& idleEmployees >0){
					if(clock.getHour()>=BuildModel.START_WORK_HOUR && clock.getHour() < BuildModel.END_WORK_HOUR){
						scheduleAction(cleanUpByContractors, time, 1);
						//scheduleWait(cleanUpByContractors, time, cleanUpByContractors.getTask());
					}
				}*/
			}		
			//	if(cleanUpByEmployees.isDone() || cleanUpByContractors.isDone() ){
			if(!dryMachinary.isInProgress() && !dryMachinary.isDone()){ //&& moveStock.isDone()){
				if(idleEmployees==0&& backToOperation.isInProgress()){
					emergencyStop(backToOperation);
//					backToOperation.setResources(0);
//					scheduleAction(dryMachinary, time, 1);
//					if(idleEmployees>0){
//						scheduleAction(backToOperation, time, idleEmployees);
//					}
				}
				if(idleEmployees >=2){ 
					scheduleAction(dryMachinary, time, (int)Math.round(0.5*idleEmployees));
					updateEmployees();
					if(idleEmployees>0){
						scheduleAction(backToOperation, time, idleEmployees);
					}
				}
				if(idleEmployees<2&&idleEmployees>0){
					scheduleAction(dryMachinary, time, idleEmployees);
					/*
					if(idleEmployees>0){
						scheduleAction(backToOperation, time, idleEmployees);
					}*/
				}
				
			}
			if(!dryMachinary.isInProgress() && !dryMachinary.isDone()){ //&& moveStock.isDone()){
				
			}
			if(!dryMachinary.isInProgress() && !dryMachinary.isDone()){ //&& moveStock.isDone()){
				
			}
				
				
				
			
			if(dryMachinary.isDone()&& moveStock.isDone()){
				if(this.getPremise().getNumberOfFloors()>1){
					if(workOnAboveFloors.isDone()){
						backToNormal();
					}
				}
				else{
					backToNormal();
				}
			}
			//	}
		}
	}
	
	public boolean getHasElecGenerator(){
		return hasElectricityGenerator;
	}
	private void saveDataTimeline(){	
		//Preparedness calculation	
		String name = "_time_"+this.companyName;
		if(this.isFlooded){   // Only print the flooded companies out in this format
			try{
				CSVWriter writer = new CSVWriter (new FileWriter(name+".csv"));
				String[] entries;	//Title Line 1
				String[] clocktime; //Title Line 2
				if(BuildModel.FORCE_STOP){
					entries = new String[(int)BuildModel.FORCE_STOP_TICK+1];
					clocktime = new String[(int)BuildModel.FORCE_STOP_TICK+24];
					clocktime[0]= "Clock Time";
					entries[0]="Employee/Tick";
					Clock temp=new Clock();
					for(int x=1; x<=(int)BuildModel.FORCE_STOP_TICK; x++){
						clocktime[x]=temp.convertTicks(x).toString();
						entries[x]=x+"";
					}
				}else{
					entries = new String[(int)backToOperation.getEndTime()+1];
					clocktime = new String[(int)backToOperation.getEndTime()+24];
					clocktime[0]= "Clock Time";
					entries[0]="Employee/Tick";
					Clock temp=new Clock();
					for(int x=1; x<=(int)backToOperation.getEndTime(); x++){
						clocktime[x]=temp.convertTicks(x).toString();
						entries[x]=x+"";
					}
				}
				writer.writeNext(clocktime);		
				writer.writeNext(entries);
				
				// Save flood data and calculation of work progress into the file 
				String[] building;
				String[] road; String[] pl=new String[productionLevelRecord.size()+1];
				String[] stock=new String[stockLevelRecord.size()+1];
				String[] stockGround=new String[stockGroundRecord.size()+1];
				String[] stockAboveGround=new String[stockAboveGroundRecord.size()+1];
				String[] stockPercentage=new String[availableStockRecord.size()+1];
				String[] avai_m=new String[availableMachinesRecord.size()+1];
				String[] avai_e=new String[availableEmployeeInPremisesRecord.size()+1];
				String[] avai_e2=new String[availableEmployeeInAidRecord.size()+1];
				String[] m1;String[] m2;String[] m3;String[] m4;String[] m5; String[] m6;
				
				//Generate different lengths of arrays accoring to the different stop-modes of the simulation
				if(BuildModel.FORCE_STOP){
					building = new String [(int)BuildModel.FORCE_STOP_TICK+100];
					road= new String [(int)BuildModel.FORCE_STOP_TICK+100];
					pl=new String[productionLevelRecord.size()+1];
					stock=new String[stockLevelRecord.size()+1];
					m1= new String [(int)BuildModel.FORCE_STOP_TICK+100];
					m2= new String [(int)BuildModel.FORCE_STOP_TICK+100];
					m3= new String [(int)BuildModel.FORCE_STOP_TICK+100];
					m4= new String [(int)BuildModel.FORCE_STOP_TICK+100];
					m5= new String [(int)BuildModel.FORCE_STOP_TICK+100];
					m5= new String [(int)BuildModel.FORCE_STOP_TICK+100];
					
				}else{
					building = new String [(int)backToOperation.getEndTime()+100];
					road =  new String [(int)backToOperation.getEndTime()+100];
				//	pl=new String[(int)backToOperation.getEndTime()+1];
					m1= new String [(int)backToOperation.getEndTime()+100];
					m2= new String [(int)backToOperation.getEndTime()+100];
					m3= new String [(int)backToOperation.getEndTime()+100];
					m4= new String [(int)backToOperation.getEndTime()+100];
					m5= new String [(int)backToOperation.getEndTime()+100];
					m6= new String [(int)backToOperation.getEndTime()+100];
				}
				
				//Write flood data in the building and road array
				building[0]="Depth of water in Building (m)";
				road[0]="Depth of water on Road (m)";
				for (Flood f: BuildModel.floodContext){
					if(f.getID().equals(this.getSerialNo())){
						double[] b = f.getBuildingWaterArray();
						double[] x=f.getBuildingWaterArray();
						for(int i=0; i<x.length; i++){
//							System.out.print(x[i]+",");
						}
						for(int i=1; i<BuildModel.ADDED_HOURS*BuildModel.TICK_PER_HOUR; i++){
							building[i]=0+"";
							road[i]=0+"";
						}
						for(int i=b.length+BuildModel.ADDED_HOURS*BuildModel.TICK_PER_HOUR;i<(int)backToOperation.getEndTime()+1;i++){
							building[i]=0+"";
							road[i]=0+"";
						}
						double[] r=f.getRoadWaterArray();
						for (int i=0; i< b.length;i++){
							building[i+BuildModel.ADDED_HOURS*BuildModel.TICK_PER_HOUR]= b[i]+"";
							road[i+BuildModel.ADDED_HOURS*BuildModel.TICK_PER_HOUR]=r[i]+"";
						}
						
					}
				}
				
				double[] count=new double[(int)backToOperation.getEndTime()+1];		//count how many man-hours at each tick	
				double[] normal=new double[((int)backToOperation.getEndTime()+1)];  // count how many hours at each tick for production before flood
				double[] available=new double[((int)backToOperation.getEndTime()+1)]; //count "500"
				double[] floodRelated=new double[(int)backToOperation.getEndTime()+1];	 // count how many man-hours on flood-related behaviours at each tick
				double[] normalOperationHours=new double[(int)backToOperation.getEndTime()+1]; //count how many man-hours per tick on normal operation ("1" and "500")
				for(int i=0;i<count.length;i++){
					count[i]=0.0; //initialise the array
					normal[i]=0.0;
					available[i]=0.0;
					floodRelated[i]=0.0;
					normalOperationHours[i]=0.0;
				}
				for (int j=0; j<this.employees.length; j++){
					String[] data; // Record the employees working history
					if(BuildModel.FORCE_STOP){
						data = new String [(int)BuildModel.FORCE_STOP_TICK+50];
					}else{
						data = new String [(int)backToOperation.getEndTime()+50];
					}
					data[0] = employees[j].getEmployeeCode()+"";
					LinkedList<BehaviourHistory> history= employees[j].getBehaviourHistory(); 
					//Go through the work history and save it into the csv file
					for(int i=0; i<history.size(); i++){
						Clock temp=new Clock();
						String bname= history.get(i).getCode()+"";
						for(int y=(int)history.get(i).getStart(); y<history.get(i).getEnd(); y++){
							temp.convertTicks((double)y);
							//For the behaviours which are not emergent, they always happen during working hours
							if(!history.get(i).getBehaviour().isEmergent()){
								if(temp.getHour()>=BuildModel.START_WORK_HOUR&&temp.getHour()<BuildModel.END_WORK_HOUR){
									data[y]=bname;
									if(!bname.contains("1000")){
										count[y]=count[y]+1;
									}
									if(bname.equals("1")){
										normal[y]=normal[y]+1;
									}
									if(bname.contains("500")){
										available[y]=available[y]+1;
									}
									if(!bname.equals("1")&& !bname.contains("1000")&&!bname.contains("500")){
										floodRelated[y]=floodRelated[y]+1;
									}
									if(bname.equals("1") || bname.contains("500")){
										normalOperationHours[y]=normalOperationHours[y]+1;
									}
								}
							}else{ //Emergent behaviours could be finished at a non-working-hour time
								data[y]=bname;
								if(!bname.contains("1000")){
									count[y]=count[y]+1;
								}
								if(!bname.equals("1")&& !bname.contains("1000")&&!bname.contains("500")){
									floodRelated[y]=floodRelated[y]+1;
								}
							}
						}
					}
					writer.writeNext(data);	
				}
				String[] title=new String[1];
				title[0]="FLOOD DATA";
				writer.writeNext(new String[3]);
				writer.writeNext(title);
				writer.writeNext(building);
				writer.writeNext(road);
				
				
				//Record the number of employees at work 
				String[] numberE;
				if(BuildModel.FORCE_STOP){
					numberE = new String [(int)BuildModel.FORCE_STOP_TICK+100];
					if(BuildModel.FORCE_STOP_TICK>notAtWork.getEndTime()+1.0){
						for (int i=(int)notAtWork.getEndTime(); i<(int)BuildModel.FORCE_STOP_TICK; i++){
							numberE[i] = numberEmployees+"";
						}
						
					}
				}else{
					System.out.println("//////////////////////"+theDayAfterFlood());
					numberE = new String [(int)backToOperation.getEndTime()+100];
					for (int i=(int)notAtWork.getEndTime(); i<(int)backToOperation.getEndTime(); i++){
						numberE[i] = numberEmployees+"";
					}
				}
				numberE[0]="Number of Employees At Work";
				for(int i=1; i< (int)notAtWork.getStartTime(); i++){
					numberE[i] = numberEmployees+"";
				}
				for(int i=(int)notAtWork.getStartTime(); i<(int)notAtWork.getEndTime(); i++){
					numberE[i]=(numberEmployees-numberVacancy)+"";
				}
				/*
				if(evacuate.isDone()){					
					for(int i=(int)evacuate.getEndTime(); i<(int)theDayAfterFlood();i++){
	//					numberE[i] ="";
					}
				}*/
				writer.writeNext(new String[3]);
				String[] metric= new String[1];
				metric[0]="METRICS";
				writer.writeNext(metric);
				writer.writeNext(numberE);
				
				
				for(int i=0; i<productionLevelRecord.size();i++){
					pl[i]=productionLevelRecord.get(i)+""; //pl[i+1]=productionLevelRecord.get(i+1)+"";
				}
				pl[0]="Production Level(%)";
				writer.writeNext(pl);
				
				for(int i=0; i<availableStockRecord.size();i++){
					stockPercentage[i]=availableStockRecord.get(i)+"";//stockPercentage[i+1]=availableStockRecord.get(i)+"";
				}
				stockPercentage[0]="Stock Percentage(%)";
				writer.writeNext(stockPercentage);
				
				for(int i=0; i<stockLevelRecord.size();i++){
					stock[i]=stockLevelRecord.get(i)+""; //stock[i+1]=stockLevelRecord.get(i)+"";
				}
				stock[0]="Stock Units";
				writer.writeNext(stock);
				
				for(int i=0; i<stockGroundRecord.size();i++){
					stockGround[i]=stockGroundRecord.get(i)+"";
				}
				stockGround[0]="Stock (on Ground) Units";
				writer.writeNext(stockGround);
				
				for(int i=0; i<stockAboveGroundRecord.size();i++){
					stockAboveGround[i]=stockAboveGroundRecord.get(i)+"";
				}
				stockAboveGround[0]="Stock (above Ground) Units";
				writer.writeNext(stockAboveGround);
								
				for(int i=0; i<availableMachinesRecord.size();i++){
					avai_m[i+1]=availableMachinesRecord.get(i)+"";
				}
				avai_m[0]="Available Machines in Total(%)";
				writer.writeNext(avai_m);
								
				for(int i=0; i<availableEmployeeInPremisesRecord.size();i++){
					avai_e[i]=availableEmployeeInPremisesRecord.get(i)+"";
				}
				avai_e[0]="Available Employees in Premises";
				writer.writeNext(avai_e);
				
				for(int i=0; i<availableEmployeeInAidRecord.size();i++){
					avai_e2[i]=availableEmployeeInAidRecord.get(i)+"";
				}
				avai_e2[0]="Available Employees for Aid";
				writer.writeNext(avai_e2);
				
				String[] count_s= new String[count.length+1]; // count "man-hours at each tick"
				for(int i=0;i<count.length;i++){
					count_s[i]=count[i]/BuildModel.TICK_PER_HOUR+"";
				}
				count_s[0]="Man-hours at each tick";
				writer.writeNext(count_s);
				double[] copy_count=new double[count.length]; // make a copy of count array
				for(int i=0; i<count.length; i++){
					copy_count[i]=count[i]/BuildModel.TICK_PER_HOUR;
				}
				String[] accumulation= new String[count.length+1]; // do an cumulation of count array		
				for(int i=1;i<copy_count.length;i++){
					copy_count[i]=copy_count[i-1]+copy_count[i];
					accumulation[i]=copy_count[i]+"";
				}				
				accumulation[0]="Man-hours completed";
				writer.writeNext(accumulation);
				
				double[] floodRelated_copy=new double[floodRelated.length]; // make a copy of  array
				for(int i=0; i<floodRelated.length; i++){
					floodRelated_copy[i]=floodRelated[i]/BuildModel.TICK_PER_HOUR;
				}
				
				String[] accFloodRelated= new String[floodRelated.length+1]; // do cumulation on the copied array		
				for(int i=1;i<floodRelated_copy.length;i++){
					floodRelated_copy[i]=floodRelated_copy[i-1]+floodRelated_copy[i];
					accFloodRelated[i]=floodRelated_copy[i]+"";
				}				
				accFloodRelated[0]="Flood realated man-hours completed";
				writer.writeNext(accFloodRelated);
				
				double[] normalOperationHours_copy=new double[normalOperationHours.length]; // make a copy 
				for(int i=0; i<normalOperationHours.length; i++){
					normalOperationHours_copy[i]=normalOperationHours[i]/BuildModel.TICK_PER_HOUR;
				}
				
				String[] accNormalOperationRelated= new String[normalOperationHours.length+1]; // do cumulation on copied array	
				for(int i=1;i<normalOperationHours_copy.length;i++){
					normalOperationHours_copy[i]=normalOperationHours_copy[i-1]+normalOperationHours_copy[i];
					accNormalOperationRelated[i]=normalOperationHours_copy[i]+"";
				}				
				accNormalOperationRelated[0]="Normal operation man-hours completed";
				writer.writeNext(accNormalOperationRelated);
				
				double[] normal_copy=new double[normal.length]; // make a copy 
				for(int i=0; i<normal.length; i++){
					normal_copy[i]=normal[i]/BuildModel.TICK_PER_HOUR;
				}
				
				
			//	String[] accNormalProduction= new String[normal_copy.length+1]; // do cumulation on copied array	
				for(int i=1;i<normal_copy.length;i++){
					normal_copy[i]=normal_copy[i-1]+normal_copy[i];
			//		accNormalProduction[i]=normal_copy[i]+"";
				}				
//				accNormalOperationRelated[0]="Normal operation (ACTURAL) man-hours completed";
//				writer.writeNext(accNormalOperationRelated);
				
				double[] available_copy=new double[available.length]; // make a copy 
				for(int i=0; i<available.length; i++){
					available_copy[i]=available[i]/BuildModel.TICK_PER_HOUR;
				}
				for(int i=1;i<available_copy.length;i++){
					available_copy[i]=available_copy[i-1]+available_copy[i];
			//		accNormalProduction[i]=normal_copy[i]+"";
				}	
				//	String[] t_m1= new String [(int)backToOperation.getEndTime()+100];
				String[] t_m2= new String [(int)backToOperation.getEndTime()+100]; //Preparedness
				String[] t_m3= new String [(int)backToOperation.getEndTime()+100]; //Response
				String[] t_m4= new String [(int)backToOperation.getEndTime()+100];//Recovery
				String[] t_m5= new String [(int)backToOperation.getEndTime()+100]; // normal operation (actual) - before flood
				String[] t_m6= new String [(int)backToOperation.getEndTime()+100];
				String[] p_m2= new String [(int)backToOperation.getEndTime()+100]; //Preparedness progress
				String[] p_m3= new String [(int)backToOperation.getEndTime()+100]; //Response progress
				String[] p_m4= new String [(int)backToOperation.getEndTime()+100];//Recovery
				String[] p_m5= new String [(int)backToOperation.getEndTime()+1]; // normal operation (actual) - before flood
				String[] p_m6= new String [(int)backToOperation.getEndTime()+1];
				String[] h_m2= new String [2]; //Preparedness Histgram
				String[] h_m3= new String [2]; //Response progress
				String[] h_m4= new String [2];//Recovery
				String[] h_m5= new String [2]; // normal operation (actual) - before flood
				String[] h_m6= new String [2];
				Clock p1=startResponse;
				Clock p2=startRecovery;				
				//To mark the preparedness stage  
				double start=liftUpITEquipments.getStartTime();
				double end =liftUpITEquipments.getEndTime();		
				if(liftUpITEquipments.isDone()||engineeringProtection.isDone()){
					if(start> engineeringProtection.getStartTime()&& engineeringProtection.getStartTime()>=0.0){
						start=engineeringProtection.getStartTime();
					}
					if(end< engineeringProtection.getEndTime()&&  end>0.0){
						end=engineeringProtection.getEndTime();
					}	
					//If lift-up/seal-doors finish during the flood, the end of preparedness stage should be the beginning of response stage 
					if (end>startResponse.convertClock()){
						end=startResponse.convertClock()-1;
					}
					//Preparedness			
					for(int i=(int)start;i<(int)end;i++){	
						double t=floodRelated[i]/BuildModel.TICK_PER_HOUR;								
						m2[i]=t+"";	
						t_m2[i]=(floodRelated_copy[i]*100)/floodRelated_copy[floodRelated_copy.length-1]+"";
						p_m2[i]=(floodRelated_copy[i]*100)/floodRelated_copy[(int)end-1]+"";
					}
					for(int i=1; i<(int)start; i++){
						m2[i]=0+"";
						t_m2[i]=0.0+"";
						p_m2[i]=0.0+"";
					}									
					for(int i=(int)end; i<floodRelated.length; i++){
						t_m2[i]=t_m2[(int)end-1];
						m2[i]=0+"";
						p_m2[i]=p_m2[(int)end-1];
					}
					h_m2[1]=floodRelated_copy[(int)end-1]*100/copy_count[copy_count.length-1]+"";
				} else{
					for(int i=0; i<floodRelated.length;i++){
						m2[i]=0+"";
						t_m2[i]=0+"";
						p_m2[i]=0+"";
					}
					h_m2[1]=0.0+"";
				}
				//normal operation
				double normal_operation=produce.getEndTime();			
				for(int i=1;i<(int)normal_operation;i++){
					double t=normal[i]/BuildModel.TICK_PER_HOUR;
					m5[i]= t+"";
					t_m5[i]=(normal_copy[i]*100)/normalOperationHours_copy[normalOperationHours_copy.length-1]+"";
					p_m5[i]= (normal_copy[i]*100)/normal_copy[normal_copy.length-1]+"";
				}
				for(int i=(int)normal_operation; i<(int)p2.convertClock();i++){
					t_m5[i]=t_m5[(int)normal_operation-1];
					p_m5[i]=p_m5[(int)normal_operation-1];
				}
				for(int i=(int)p2.convertClock(); i<p_m5.length;i++){
	
					p_m5[i]=100.0+"";
				}
				
				/*
				for(int i=(int)normal_operation; i<normal.length);i++){
					p_m5[i]=p_m5[(int)normal_operation-1];
				}*/
				h_m5[1]=normal_copy[normal_copy.length-1]*100/copy_count[copy_count.length-1]+"";
				//Response
				if(!this.isFloodedInNight){
					double[] temp=new double[floodRelated.length];
					temp[(int)p1.convertClock()]=floodRelated[(int)p1.convertClock()];
					for(int i=(int)p1.convertClock(); i<(int)p2.convertClock();i++){
						temp[i]=floodRelated_copy[i]-floodRelated_copy[(int)p1.convertClock()-1];
//						System.out.print(floodRelated_copy[i]+",");
					
					}
					t_m3[(int)p1.convertClock()]=(temp[(int)p1.convertClock()]*100)/floodRelated_copy[floodRelated_copy.length-1]+"";
					for(int i=(int)p1.convertClock();i<(int)p2.convertClock();i++){
						double t=floodRelated[i]/BuildModel.TICK_PER_HOUR;
						m3[i]=t+"";
						t_m3[i]=(temp[i]*100)/floodRelated_copy[floodRelated_copy.length-1]+"";
						double d=(temp[i]*100)/(floodRelated_copy[(int)p2.convertClock()-1]-floodRelated_copy[(int)p1.convertClock()]);
						if(d>100.0){
							d=100.0;
						}
						p_m3[i]=d+"";
					}	
					for(int i=1; i<(int)p1.convertClock(); i++){
						t_m3[i]=0.0+"";
						m3[i]=0.0+"";
						p_m3[i]=0.0+"";
					}
					for(int i=(int)p2.convertClock(); i<floodRelated.length; i++){
						t_m3[i]=t_m3[(int)p2.convertClock()-1];
						m3[i]=0.0+"";
						p_m3[i]=p_m3[(int)p2.convertClock()-1];
					}
					h_m3[1]=(floodRelated_copy[(int)p2.convertClock()-1]-floodRelated_copy[(int)p1.convertClock()])*100/copy_count[copy_count.length-1]+"";
				} else{
					for(int i=1; i<m3.length; i++){
						t_m3[i]=0.0+"";
						m3[i]=0.0+"";
						p_m3[i]=0.0+"";
					}
					h_m3[1]=0.0+"";
				}
				
				//Recovery
				double[] temp2=new double[floodRelated.length];
		//		temp2[(int)p2.convertClock()]=floodRelated_copy[(int)p2.convertClock()];
				
				for(int i=(int)p2.convertClock(); i<floodRelated.length;i++){
					temp2[i]=floodRelated_copy[i]-floodRelated_copy[(int)p2.convertClock()-1];					
				}
				temp2[(int)p2.convertClock()]=floodRelated[(int)p2.convertClock()];
				t_m4[(int)p2.convertClock()]=(temp2[(int)p2.convertClock()]*100)/floodRelated_copy[floodRelated_copy.length-1]+"";
				p_m4[(int)p2.convertClock()]=(temp2[(int)p2.convertClock()]*100)/(floodRelated_copy[floodRelated_copy.length-1]-floodRelated_copy[(int)p2.convertClock()])+"";
				for(int i=(int)p2.convertClock()+1;i<floodRelated.length;i++){
					double t=floodRelated[i]/BuildModel.TICK_PER_HOUR;					
					t_m4[i]=(temp2[i]*100)/floodRelated_copy[floodRelated_copy.length-1]+"";
					p_m4[i]=(temp2[i]*100)/(floodRelated_copy[floodRelated_copy.length-1]-floodRelated_copy[(int)p2.convertClock()])+"";
				}			
				for(int i=1; i<(int)p2.convertClock(); i++){
					t_m4[i]=0.0+"";
					m4[i]=0.0+"";
					m6[i]=0.0+"";	// for array available		
					p_m4[i]=0.0+"";
					p_m6[i]=0.0+"";
				}
				h_m4[1]=(floodRelated_copy[floodRelated_copy.length-1]-floodRelated_copy[(int)p2.convertClock()])*100/copy_count[copy_count.length-1]+"";
				h_m6[1]=available_copy[available_copy.length-1]*100/copy_count[copy_count.length-1]+"";
				m1[0]="Mitigation";
				m2[0]= "Preparedness man-hours";
				m3[0]= "Response man-hours";
				m4[0]= "Recovery man-hours";
				m5[0]="Normal operation (Actual) man-hours";
				
								
				for(int i=(int)p2.convertClock(); i<available.length; i++){
					m6[i]=available[i]/BuildModel.TICK_PER_HOUR+"";
					t_m5[i]=(normalOperationHours_copy[i]*100)/normalOperationHours_copy[normalOperationHours_copy.length-1]+"";
					p_m6[i]=(available_copy[i]*100)/available_copy[available_copy.length-1]+"";
				}
				
				m6[0]="Normal operation (Available) man-hours";
				
				//	t_m1[0]="Mitigation";
				t_m2[0]= "Preparedness (%)";
				t_m3[0]= "Response (%)";
				t_m4[0]= "Recovery (%)";
				t_m5[0]="Normal operation (%)";
				//t_m6[0]="";
				
				p_m2[0]= "Preparedness Progress(%)";
				p_m3[0]= "Response Progress(%)";
				p_m4[0]= "Recovery Progress(%)";
				p_m5[0]="Normal Operation (Actual) Progress(%)";
				p_m6[0]="Normal Operation (Available) Progress(%)";
				
				h_m2[0]= "Preparedness";
				h_m3[0]= "Response";
				h_m4[0]= "Recovery";
				h_m5[0]="Normal Operation (Actual)";
				h_m6[0]="Normal Operation (Available)";
				
				writer.writeNext(new String[1]);
				String[] t1=new String[1];
				t1[0]="MAN HOURS PER TICK";
				writer.writeNext(t1);	
				writer.writeNext(m1);				
				writer.writeNext(m2);					
				writer.writeNext(m3);					
				writer.writeNext(m4);
				writer.writeNext(m5);
				writer.writeNext(m6);
				
				writer.writeNext(new String[1]);
				//	writer.writeNext(t_m1);	
				String[] t2= new String[2];
				t2[0]="CUMULATIVE PERCENTAGES";
				writer.writeNext(t2);
				writer.writeNext(t_m2);					
				writer.writeNext(t_m3);					
				writer.writeNext(t_m4);
				writer.writeNext(t_m5);
				
				writer.writeNext(new String[1]);
				String[] t3=new String[1];
				t3[0]="Work progress";
				writer.writeNext(t3);							
				writer.writeNext(p_m2);					
				writer.writeNext(p_m3);					
				writer.writeNext(p_m4);
				writer.writeNext(p_m5);
				writer.writeNext(p_m6);
				
				writer.writeNext(new String[1]);
				String[] t4=new String[1];
				t4[0]="Histogram";
				writer.writeNext(t4);							
				writer.writeNext(h_m2);					
				writer.writeNext(h_m3);					
				writer.writeNext(h_m4);
				writer.writeNext(h_m5);
				writer.writeNext(h_m6);
			
				writer.writeNext(new String[1]);
				String[] att={"ATTRIBUTES"};
				writer.writeNext(att);
				String[] trust=new String[2];
				trust[0] = "trust EA";
				trust[1] = String.valueOf(trustEA);
				writer.writeNext(trust);
				String[] sub=new String[2];
				sub[0] = "Subscribe for EA warnings";
				sub[1] = String.valueOf(this.getSubscriber());	
				writer.writeNext(sub);
				String[] flooded=new String[2];
				flooded[0] = "Has been flooded";
				flooded[1] = String.valueOf(isFlooded);
				writer.writeNext(flooded);
				String[] bundWall=new String[2];
				bundWall[0] = "Has bund wall";
				bundWall[1] = String.valueOf(hasBundWall);
				writer.writeNext(bundWall);
				String[] nightFlood=new String[2];
				nightFlood[0] = "Flooded in the night";
				nightFlood[1] = String.valueOf(isFloodedInNight);
				writer.writeNext(nightFlood);
				String[] warning=new String[2];
				warning[0] = "Received any type of warning";
				warning[1] = String.valueOf(receivedWarningSave);
				writer.writeNext(warning);
				String[] engineer=new String[2];
				engineer[0] = "Has engieers onsite";
				engineer[1] = String.valueOf(this.hasEngineers);
				writer.writeNext(engineer);
				String[] s1=new String[2];
				s1[0]="Cash available";
				s1[1]= String.valueOf(this.cashAvailableForRecovery);
				writer.writeNext(s1);
				String[] check=new String[2];
				check[0] = "Start response";
				check[1] = startResponse.toString();
				String[] check2=new String[2];
				check2[0]="Start Recovery";
				check2[1]=startRecovery.toString();
				writer.writeNext(check);
				writer.writeNext(check2);
				LinkedList<SME> neighbours=this.getNeighbours();
				String[] n = new String[neighbours.size()+1];
				n[0]="Neighbours";
				for(int i=0;i<neighbours.size();i++){
					n[i+1]= neighbours.get(i).getName();
				}
				writer.writeNext(n);
				String[] traffic= new String[2];
				traffic[0]="Traffic during the flood hours";
				traffic[1]=String.valueOf(trafficOn);
				writer.writeNext(traffic);
				String[] absentees= new String[2];
				absentees[0]="Number of absentees";				
				absentees[1]=this.getNumberVacancy()+"";
				writer.writeNext(absentees);
				
				String[] aid=new String[this.getMutualAider().size()+2];
				aid[0]="Mutual aid";
				for(int i=1;i<=this.getMutualAider().size();i++){
					aid[i] =this.getMutualAider().get(i-1).getName(); 
				}
				writer.writeNext(aid);
				
				String[] msg=new String[2];
				msg[0]="SME's Received Messages";
				writer.writeNext(msg);
				String[] msg_1= new String[2];
				for(int i=0; i<this.getReceiver().getReceivedMessages().size(); i++){
					msg_1[0]=this.getReceiver().getReceivedMessages().get(i).toString();
					writer.writeNext(msg_1);
				}
				
				
				String[] wait=new String[1];
				wait[0]="WAIT";
				writer.writeNext(new String[2]);
				writer.writeNext(wait);

				for(BehaviourSME b: behaviours){
					String[] recordingWait= new String[2];
					if(b.getBehaviourName().contains("wait")){
						recordingWait[0]=b.getBehaviourName();
						recordingWait[1]=b.getStartTime()+"-"+b.getEndTime();
						writer.writeNext(recordingWait);
					}

				}

				writer.close();
			}
			catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}
	private double theDayAfterFlood(){
		double t=0.0;	
		Clock c=startRecovery;			
		if(c.getHour()<9){
			c.setHour(9);
			c.setMin(0);
			t=c.convertClock();
		}
		if(c.getHour()>=9){
			c.setHour(9);
			c.setMin(0);
			c.setDay(c.getDay()+1);
			t=c.convertClock();
		}
		for(int i =(int)evacuate.getEndTime(); i<(int)t; i++){

		}
		return t;
	}
	/**
	 * Saves the data in to the format with the headings: Employee, behaviour, start, end
	 */
	private void saveDataSecond(){
		String name = "_Employee_behaviour_"+this.companyName;
		try{
			CSVWriter writer = new CSVWriter (new FileWriter(name+".csv"),',', CSVWriter.NO_QUOTE_CHARACTER);
			String[] entries = {"Employee", "Behaviour", "Start", "End"};
			writer.writeNext(entries);

			for (int j=0; j<this.employees.length; j++){

				String[] data = new String [4];
				data[0] = employees[j].getEmployeeCode()+"";
				LinkedList<BehaviourHistory> history= employees[j].getBehaviourHistory();
				for(int i=0; i<history.size(); i++){
					data[1]= history.get(i).getName();
					data[2] = history.get(i).getStart()+"";
					data[3] = history.get(i).getEnd()+"";	
					writer.writeNext(data);
				}

			}
			writer.close();
		}
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	/**
	 * Saves the data in the format with headings of start time and end time of all behaviours
	 */
	private void saveData(){
		String name = "_p_"+this.companyName;
		if(this.isFlooded){
			try {
				CSVWriter writer = new CSVWriter (new FileWriter(name+".csv"),',', CSVWriter.NO_QUOTE_CHARACTER);
				String[] entries = new String [this.behaviours.size()*2+1];
				entries[0] = "Employee";
				int title=0;
				for (int i=0; i< this.behaviours.size(); i++){				
					entries [title+1] = behaviours.get(i).getBehaviourName()+" START";
					entries [title+2] = behaviours.get(i).getBehaviourName()+" END";
					title= title+2;
				}
				writer.writeNext(entries);

				for (int j=0; j<this.employees.length; j++){
					int temp=0;
					String[] data = new String [this.behaviours.size()*2+1];
					data[0] =  employees[j].getEmployeeCode()+"";
					for(int y=1; y<data.length; y++){
						data[y]="";
					}

					for (int i=0; i< this.behaviours.size(); i++){ 
						String bname = behaviours.get(i).getBehaviourName();
						if(employees[j].hasBehaviour(bname)){
							Employee e = employees[j];
							Clock c = new Clock();
							if(e.getBHbyName(bname).size()<2){
								double t_start = e.getBHbyName(bname).get(0).getStart();
								String s1=c.convertTicks(t_start).toString();
								double t_end = e.getBHbyName(bname).get(0).getEnd();
								String s2 = c.convertTicks(t_end).toString();
								data [temp+1] = t_start+"";
								data [temp+2] = t_end+"";
								//	data [i+1] = t_start+"( "+s1+" )"+" - "+ t_end + "( "+s2+" )";
								temp=temp+2;
							}
							if(e.getBHbyName(bname).size()>1){
								for (int x=0; x<e.getBHbyName(bname).size(); x++){
									double t_start = e.getBHbyName(bname).get(x).getStart();
									String s1=c.convertTicks(t_start).toString();
									double t_end =e.getBHbyName(bname).get(x).getEnd();
									String s2 = c.convertTicks(t_end).toString();
									//data [i+1] = data[i+1] +t_start+"( "+s1+" )"+" - "+ t_end + "( "+s2+" );";
									data [temp+1] = t_start+"";
									data [temp+2]= t_end+"" ;
									temp=temp+2;
								}
							}
						}
						/*
						 *Maybe change to whole sme's behaviour - waiting, instead of allocating this to every single employee.
						 **/
						/*
					else if(getBehaviour(bname).isDone() && getBehaviour(bname).getBehaviourName().contains("wait")){
					//	System.out.println("--------------------------------------------------------"+getBehaviour(entries[i+1]).toString());
						double t1 = getBehaviour(bname).getStartTime();
						double t2 = getBehaviour(bname).getEndTime();
						data [i+1] = t1+" - "+ t2 ;
					} */
						else{
							data[temp+1] = "" ;
							data[temp+2] ="";
						}	

					}
					writer.writeNext(data);

				}
				writer.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	/**
	 * Saves the data in the format with headings all behaviours.
	 */
	private void saveEmployeesData(){
		String name = "_"+this.companyName;
		try {
			//CSVWriter writer = new CSVWriter (new FileWriter(name+".csv"));
			CSVWriter writer = new CSVWriter (new FileWriter(name+".csv"),',', CSVWriter.NO_QUOTE_CHARACTER);
			String[] entries = new String [this.behaviours.size()+1];
			entries[0] = "Employee";
			for (int i=0; i< this.behaviours.size(); i++){
				entries [i+1] = behaviours.get(i).getBehaviourName();
			}
			writer.writeNext(entries);

			for (int j=0; j<this.employees.length; j++){
				String[] data = new String [this.behaviours.size()+1];
				data[0] = employees[j].getEmployeeCode()+"";
				for(int y=1; y<data.length; y++){
					data[y]="";
				}

				for (int i=0; i< this.behaviours.size(); i++){
					if(employees[j].hasBehaviour(entries[i+1])){
						Employee e =employees[j];
						Clock c = new Clock();
						if(e.getBHbyName(entries[i+1]).size()<2){
							double t_start = e.getBHbyName(entries[i+1]).get(0).getStart();
							String s1=c.convertTicks(t_start).toString();
							double t_end =e.getBHbyName(entries[i+1]).get(0).getEnd();
							String s2 = c.convertTicks(t_end).toString();
							data [i+1] = t_start+"-"+ t_end ;
							//	data [i+1] = t_start+"( "+s1+" )"+" - "+ t_end + "( "+s2+" )";
						}
						if(e.getBHbyName(entries[i+1]).size()>1){
							for (int x=0; x<e.getBHbyName(entries[i+1]).size(); x++){
								double t_start = e.getBHbyName(entries[i+1]).get(x).getStart();
								String s1=c.convertTicks(t_start).toString();
								double t_end =e.getBHbyName(entries[i+1]).get(x).getEnd();
								String s2 = c.convertTicks(t_end).toString();
								//data [i+1] = data[i+1] +t_start+"( "+s1+" )"+" - "+ t_end + "( "+s2+" );";
								data [i+1] = t_start+"-"+ t_end ;
							}
						}
					}
					/*
					else if(getBehaviour(entries[i+1]).isDone() && getBehaviour(entries[i+1]).getBehaviourName().contains("wait")){
					//	System.out.println("--------------------------------------------------------"+getBehaviour(entries[i+1]).toString());
						double t1 = getBehaviour(entries[i+1]).getStartTime();
						double t2 = getBehaviour(entries[i+1]).getEndTime();
						data [i+1] = t1+" - "+ t2 ;
					} */
					else{
						data[i+1] = "" ;
					}					 
				}
				writer.writeNext(data);

			}
			writer.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	private void printEmployeeStatus() {
		for (int i=0; i< employees.length; i++){
			System.out.println(employees[i].toString());
		}

	}
	public void getSimStop(){

	}

	/**
	 * Updates the list of alerts and get newly received alerts.
	 */
	@Override	
	public void updateReceiver() {
		// TODO Auto-generated method stub
		LinkedList<FloodWarning> alerts = this.receiver.getAlerts();
		if(alerts.size()>0){
			this.receiveWarning = true;
			this.receivedWarningSave=true;
			for (int i=0; i<alerts.size(); i++){				
				String s =alerts.get(i).toString();
				//System.out.println("At time "+ time + this.companyName +" receive Updates: "+s);
			}
		}
		alerts.clear();
		//10/03/2015
		LinkedList<Message> msgs=this.getReceiver().getReceivedMessages();
		if(msgs.size()>msgNumber){
			for (int i=msgs.size()-1; i>msgNumber-1; i--){
				//				Organization x=msgs.get(i).getMsgSender();
				String x=msgs.get(i).getMsgSender();
				String msg=msgs.get(i).getMessage();
				String[] temp=msg.split(",");
				System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"+this.getName()+" RECEIVED: "+msg + "   idle employees = "+idleEmployees +"; "+ " back to operation is in progress: "+backToOperation.isInProgress());
				if(msg.contains("service") && msg.contains("clean")){
					ServiceCompany s=searchCompanyByName(x);
					comingServiceCom.add(s);					
					double t=Double.parseDouble(temp[2]);
					if (!cleanUpByContractors.isDone() && !cleanUpByContractors.isInProgress()){
						if(clock.getHour()>=BuildModel.START_WORK_HOUR && clock.getHour() < BuildModel.END_WORK_HOUR){
							if(idleEmployees >0){ 
								scheduleAction(cleanUpByContractors, time, 1);
							}
							//if there is no idle employees and backToOperation is not in progress
							if(idleEmployees==0 && !backToOperation.isInProgress()){
								//Find the ongoing behaviour with lowest priority
								double pc=40.0;
								LinkedList<BehaviourSME> compare = new LinkedList<BehaviourSME>();
								for (BehaviourSME b: behaviours){			
									if (b.isInProgress()){
										double p=b.getPriority();
										if(p<pc){
											compare.add(b);
											pc=p;
										}
									}
								}
								//stop the behaviour and schedule cleanUpByContractors; if there is any idle employee, allocate them to the 
								//stopped behaviour
								emergencyStop(compare.getLast());
								System.out.println("%%%%%%%%%%%%%%%  "+ compare.getLast().toString() +" is stopped. idle employee ="+idleEmployees );
								compare.getLast().setDone(false);
								double task=compare.getLast().remainTask(time);
								compare.getLast().setTask(task);
								scheduleAction(cleanUpByContractors, time, 1);
								if(idleEmployees>0){									
									scheduleAction(compare.getLast(),time,1);									
								}/*
								else{
									scheduleAction(compare.getLast(),time+cleanUpByContractors.getDuration(),1);
								}*/
							}
							
							if(backToOperation.isInProgress()){
								emergencyStop(backToOperation);
//								backToOperation.setResources(0);
								scheduleAction(cleanUpByContractors, time, 1);
								
								if(idleEmployees>0){
									scheduleAction(backToOperation, time, idleEmployees);
								}
							}							
						}
					}
				}
				if(msg.contains("request")&& msg.contains("mutualAid")){
					int t= Integer.parseInt(temp[2]);
					int giving= random.nextInt(t-1)+1;
					String confirm = "reply,givingAid,"+giving;
//					ManufactureSME aid=searchSMEByName(x);
//					System.out.println("%%%%%%%%%%%%%%%%%%%%"+aid.getName()+"   isflooded"+aid.isFlooded + "        perceived Danger "+aid.getPerceivedDanger());
					if(!this.isFlooded && !this.getPerceivedDanger()){
						this.sender.smeToSME(confirm, x);
					}else{
						String reject="reject,givingAid,"+time;
						this.sender.smeToSME(reject, x);
					}
				}
				
				if(msg.contains("givingAid")){
					if(msg.contains("reply")){
						invokeMutualAid(msg);
					}
					if(msg.contains("reject")){
						System.out.println("              The mutual aid request is rejected!!!!                    ");
					}
				}
			}
		}
		msgNumber=msgs.size();
	}
	public void invokeMutualAid(String msg){	
		String[] message=msg.split(",");
		System.out.println(this.getName()+"            received "+message);
//		SME aid=this.getMutualAider().get(0);
		availableMachinesMutualAid=Double.parseDouble(message[2]);
		int available = (int)(numberEmployees*availableMachinesMutualAid/100);
		if(available<1){
			available=1;
		}
		System.out.println(this.getName()+"            Mutual aid employees="+available+ "    available Machines="+availableMachinesMutualAid);
		while(idleEmployees<available){
			pauseBehaviour(searchLowestPriority());			
		}
		if(!workWithAid.isInProgress() && !workWithAid.isDone()&&idleEmployees>=available){		
			workWithAid.setTask(available*BuildModel.WORKINGHOURS*BuildModel.TICK_PER_HOUR*aidDays);
			if(clock.getHour()>= BuildModel.START_WORK_HOUR  && clock.getHour() < BuildModel.END_WORK_HOUR ){
				scheduleAction(workWithAid, time, available);	
			}else{
				Clock c=clock;
				double timeForAid=c.nextDay();
				scheduleAction(workWithAid, timeForAid, available);
			}
		}				
	}
	/**
	 * Find the ongoing behaviour with lowest priority
	 * @return the ongoing behaviour with lowest priority
	 */
	private BehaviourSME searchLowestPriority(){
		double pc=HIGHEST_P;
		BehaviourSME behaviour= new BehaviourSME(this, " ", 0, 50.0, false,555,"post", false);
		//LinkedList<BehaviourSME> compare = new LinkedList<BehaviourSME>();
		for (BehaviourSME b: behaviours){			
			if (b.isInProgress()){
				double p=b.getPriority();
				if(p<=pc){					
					pc=p;
					behaviour=b;
					System.out.println(behaviour.getBehaviourName()+"      has lowest priority");
				}
			}
		}
		System.out.println(behaviour.getBehaviourName()+"      has lowest priority");
		return behaviour;
	}
	private ServiceCompany searchCompanyByName (String s){
		ServiceCompany found=new ServiceCompany(3, "");
		for(ServiceCompany x: this.GetServiceCompanyList()){			
			if(x.getCompanyName().equals(s)){
				found =x;
			}
			else{
				found=null;
			}
		}
	
		return found;
	}
	private ManufactureSME searchSMEByName (String s){
		ManufactureSME found=new ManufactureSME();
		for(SME sme: BuildModel.smeContext){
			int i=sme.getName().compareTo(s);
			if(i==0){
				found =(ManufactureSME)sme;
			}
		}
		return found;
	}
	public void endBehaviours(){
		if (evacuate.isInProgress() && time >= evacuate.getExecutedTime()+ evacuate.getDuration() ){
			terminateBehaviour(evacuate);
			System.out.println("*******************"+this.companyName+" Evacuation is done. idle employees: "+ idleEmployees + " at time: " + time);				
		}
		if (liftUpITEquipments.isInProgress() && time>=liftUpITEquipments.getExecutedTime()+liftUpITEquipments.getDuration() ){
			terminateBehaviour(liftUpITEquipments);	
		//	stock.setStockUnitsGround(0.0);
		//	stock.setStockUnitsAboveGround(stock.getStockLevel()); // Move all the stock on the ground level to above ground level
			System.out.println("*******************"+this.companyName+" finished lift-up IT equipments. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if (liftUpStock.isInProgress() && time>=liftUpStock.getExecutedTime()+liftUpStock.getDuration() ){
			terminateBehaviour(liftUpStock);	
			System.out.println("*******************"+this.companyName+" finished lift-up stock. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if(hasEngineers){
			if (engineeringProtection.isInProgress()&& time>=engineeringProtection.getExecutedTime()+engineeringProtection.getDuration()){
				terminateBehaviour(engineeringProtection);	
				System.out.println("*******************"+this.companyName+" finished sealing doors. idle employees: "+ idleEmployees + " at time: " + time);
			}
		}
		if(time >= waitToEvacuate.getExecutedTime()+ waitToEvacuate.getDuration() && waitToEvacuate.isInProgress()){
			terminateWait(waitToEvacuate);
			System.out.println("*******************"+this.companyName+" finished waiting to evacuate. idle employees: "+ idleEmployees + " at time: " + time);
		}
		// restoring the power supply
		if(time >= contactElectricians.getExecutedTime()+contactElectricians.getDuration() && contactElectricians.isInProgress()){
			terminateBehaviour(contactElectricians);	
			System.out.println("*******************"+this.companyName+" contacted electricians. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if(time >= restorePower.getExecutedTime()+restorePower.getDuration() && restorePower.isInProgress()){
			terminateBehaviour(restorePower);
			setPowerOn(true);
			
			System.out.println("*******************"+this.companyName+" restored the power. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if(time >= waitForElectricians.getExecutedTime()+waitForElectricians.getDuration() && waitForElectricians.isInProgress()){
			terminateWait(waitForElectricians);
			//	updateOperationLevel();
			System.out.println("*******************"+this.companyName+" finished waiting for electricians. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if(time >= useElectricityGenerator.getExecutedTime()+useElectricityGenerator.getDuration() && useElectricityGenerator.isInProgress()){
			terminateBehaviour(useElectricityGenerator);
			setPowerOn(true);
			//		updateOperationLevel();
			System.out.println("*******************"+this.companyName+" used electricity generator. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if(time >= hireElectricityGenerator.getExecutedTime()+hireElectricityGenerator.getDuration() && hireElectricityGenerator.isInProgress()){
			terminateBehaviour(hireElectricityGenerator);
			this.hasElectricityGenerator = true;
			//	updateOperationLevel();
			System.out.println("*******************"+this.companyName+" hired electricity generator. idle employees: "+ idleEmployees + " at time: " + time);
		}
		// sorting out insurance
		if (time >= contactInsurer.getExecutedTime()+contactInsurer.getDuration() && contactInsurer.isInProgress()){
			terminateBehaviour(contactInsurer);
			//		updateOperationLevel();
			System.out.println("*******************"+this.companyName+" contacted the insurer. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if (time >= catalogueDamage.getExecutedTime()+catalogueDamage.getDuration() && catalogueDamage.isInProgress()){
			terminateBehaviour(catalogueDamage);
			//	updateOperationLevel();
			System.out.println("*******************"+this.companyName+" cataloged damages. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if(time >= sourceMoney.getExecutedTime()+ sourceMoney.getDuration() && sourceMoney.isInProgress()){
			terminateBehaviour(sourceMoney);
			hasCashNow=true;
			//	updateOperationLevel();
			System.out.println("*******************"+this.companyName+" sourced money. idle employees: "+ idleEmployees + " at time: " + time);
		}		
		if(time >= waitInsurancePayment.getExecutedTime()+ waitInsurancePayment.getDuration() && waitInsurancePayment.isInProgress()){
			terminateWait(waitInsurancePayment);
			hasCashNow=true;
			//	updateOperationLevel();
			System.out.println("*******************"+this.companyName+" finished waiting for payment. idle employees: "+ idleEmployees + " at time: " + time);
		}
		//maintaining supply chain
		if (time >= directLandline.getExecutedTime()+ directLandline.getDuration() &&  directLandline.isInProgress()){
			terminateBehaviour( directLandline);
			//		updateOperationLevel();
			System.out.println("*******************"+this.companyName+" directed landline. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if(time >= contactSuppliers.getExecutedTime()+ contactSuppliers.getDuration() && contactSuppliers.isInProgress()){
			terminateBehaviour(contactSuppliers);
			//	updateOperationLevel();
			System.out.println("*******************"+this.companyName+" contacted suppliers. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if(time >= contactCustomers.getExecutedTime()+ contactCustomers.getDuration() && contactCustomers.isInProgress()){
			terminateBehaviour(contactCustomers);
			//	updateOperationLevel();
			System.out.println("*******************"+this.companyName+" contacted customers start from" + contactCustomers.getStartTime() + " and end at"
					+contactCustomers.getEndTime() +". Idle employees: "+ idleEmployees + " at time: " + time);
		}
		//cleaning, repair and recovery
		if (time >= contactLandlord.getExecutedTime()+contactLandlord.getDuration() && contactLandlord.isInProgress()){
			terminateBehaviour(contactLandlord);
			//	updateOperationLevel();
			System.out.println("*******************"+this.companyName+" contacted landlord. idle employees: "+ idleEmployees + " at time: " + time);
		}

		if(time >= workOnAboveFloors.getExecutedTime()+ workOnAboveFloors.getDuration() && workOnAboveFloors.isInProgress()){
			terminateBehaviour(workOnAboveFloors);
			//	updateOperationLevel();
			System.out.println("*******************"+this.companyName+" can work on above floors now. idle employees: "+ idleEmployees + " at time: " + time);
		}

		if (time >= contactContractors.getExecutedTime()+ contactContractors.getDuration() &&  contactContractors.isInProgress()){
			terminateBehaviour( contactContractors);
			//10/03/2015
			ServiceCompany x=this.GetServiceCompanyList().get(0);
			this.getSender().sendMsgToService("request,cleanUp,"+time, x.getCompanyName());
			System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"+this.getName()+"SENT A REQUEST FOR CLEANUP");
			System.out.println("*******************"+this.companyName+" contacted a contractor for cleaning up. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if (time >= waitContractors.getExecutedTime()+ waitContractors.getDuration() &&  waitContractors.isInProgress()){
			terminateWait( waitContractors);	
			System.out.println("*******************"+this.companyName+" finished waiting for the contractor. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if (time >= cleanUpByContractors.getExecutedTime()+ cleanUpByContractors.getDuration() && cleanUpByContractors.isInProgress()){
			//		terminateBehaviour(cleanUpByContractors);
			terminateBehaviour(cleanUpByContractors);
			//10/03/2015
			String m= "finish,cleanUp,"+cleanUpByContractors.getEndTime();
			ServiceCompany x= this.GetServiceCompanyList().get(0);//this.comingServiceCom.get(0);
			this.getSender().sendMsgToService(m, x.getCompanyName());
			System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"+this.getName()+"HAS DONE FOR CLEANUP");
			System.out.println("*******************"+this.companyName+" finished cleaning up by the contractor. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if (time >= cleanUpByEmployees.getExecutedTime()+cleanUpByEmployees.getDuration() && cleanUpByEmployees.isInProgress()){
			terminateBehaviour(cleanUpByEmployees);
			
			System.out.println("*******************"+this.companyName+" finished cleaning up by employees. idle employees: "+ idleEmployees + " at time: " + time);			
		}
		if (time >= dryMachinary.getExecutedTime()+dryMachinary.getDuration() && dryMachinary.isInProgress()){
			terminateBehaviour(dryMachinary);
		
			
			System.out.println("*******************"+this.companyName+" fixed machinary. idle employees: "+ idleEmployees + " at time: " + time);
		}			
		if (time >= moveStock.getExecutedTime()+ moveStock.getDuration() &&  moveStock.isInProgress()){
			terminateBehaviour( moveStock);
			
			System.out.println("*******************"+this.companyName+" moved the stock. idle employees: "+ idleEmployees + " at time: " + time);
		}

		if (time >= backToOperation.getExecutedTime()+backToOperation.getDuration() && backToOperation.isInProgress()){
			terminateBehaviour( backToOperation);
			
			System.out.println("*******************"+this.companyName+" is back to production. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if (time >= notAtWork.getExecutedTime()+ notAtWork.getDuration() &&  notAtWork.isInProgress()){
			terminateBehaviour(notAtWork);			
			System.out.println("*******************"+this.companyName+"some people are not at work. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if (time >= workWithAid.getExecutedTime()+ workWithAid.getDuration() &&  workWithAid.isInProgress()){
			terminateBehaviour(workWithAid);	
			availableMachinesMutualAid=0;
			workWithAid.setResources(0);
			System.out.println("*******************"+this.companyName+" send people to mutual aid partners. idle employees: "+ idleEmployees + " at time: " + time);
		}
		if (time >= requestAid.getExecutedTime()+ requestAid.getDuration() &&  requestAid.isInProgress()){
			terminateBehaviour(requestAid);	
			SME aid=this.getMutualAider().get(0);
				if(!aid.isFlooded && !aid.getPerceivedDanger()){
						this.sender.smeToSME("request,mutualAid,10", aid.getName());
				}
			System.out.println("*******************"+this.companyName+"some people are not at work. idle employees: "+ idleEmployees + " at time: " + time);
		}

	}
	/**
	 * Initialises a set of behaviours a manufacture SME has, e.g., evacuation, lift-up, clean-up,
	 * contacting insurance company.
	 * 
	 */
	public void initialiseBehaviours(){

		behaviours = new LinkedList<BehaviourSME>();
		//pre and during flood;
		backToOperation = new BehaviourSME(this, "back to production", 10.0, 3000.0*employeesAtWork*BuildModel.TICK_PER_HOUR, false,500, "post",true);
		//backToOperation.setTaskStats(min, max);
		produce = new BehaviourSME (this, "production", 30.0, 3000.0* employeesAtWork*BuildModel.TICK_PER_HOUR, false,1, "normal", true);
		liftUpITEquipments = new BehaviourSME(this, "lift up IT", 40.0, 0.5*numberEmployees*BuildModel.TICK_PER_HOUR, true,2, "pre/during", true);
		liftUpITEquipments.setTask(liftUpITEquipments.setTaskStats(0.5, 1.0)*numberEmployees); //changed from 5 to 1.0 on 07/05/2015
		liftUpStock = new BehaviourSME(this, "lift up stock", 40.0, 0.5*numberEmployees*BuildModel.TICK_PER_HOUR, true,31, "pre/during", true);
		liftUpStock.setTask(liftUpStock.setTaskStats(1.0, 5.0)*numberEmployees);
		waitToEvacuate = new BehaviourSME(this,"wait for rescue/to evacuate", 1, 5.0*BuildModel.TICK_PER_HOUR, false,4,"during", false);
		//	waitToEvacuate.setTask(waitToEvacuate.setTaskStats(0.5, 8.0));
		evacuate = new BehaviourSME(this, "evacuation", 40.0, 1.0*this.employeesAtWork*BuildModel.TICK_PER_HOUR, true,5,"pre/during", false);
		evacuate.setTask(evacuate.setTaskStats(0.5, 6.0)*numberEmployees);
		//	notReturnToWork = new BehaviourSME(this, "not return to work", 20, 1.0*this.employeesAtWork, false, 500, "pre/during",false);
		contactElectricians = new BehaviourSME(this, "contact engineers", 30.0, 2.0*BuildModel.TICK_PER_HOUR, false,6,"post", false);
		contactElectricians.setTask(contactElectricians.setTaskStats(0.5, 48.0));
		waitForElectricians = new BehaviourSME(this, "wait for electricians", 1, 20.0*BuildModel.TICK_PER_HOUR, false,7,"post", false); // has to be re-implimented
		//	waitForElectricians.setTask(waitForElectricians.setTaskStats(0.5, 120.0));
		restorePower = new BehaviourSME (this, "restore power", 40.0, 30.0*BuildModel.TICK_PER_HOUR, false,8,"post", false);
		restorePower.setTask(restorePower.setTaskStats(0.5, 5.0*BuildModel.WORKINGHOURS));

		useElectricityGenerator = new BehaviourSME(this, "use electricity generator", 30.0, 2.0*BuildModel.TICK_PER_HOUR, false,9,"post", false);
		useElectricityGenerator.setTask(useElectricityGenerator.setTaskStats(0.5, 2.0*BuildModel.WORKINGHOURS));

		hireElectricityGenerator = new BehaviourSME(this, "hire electricity generator", 29.0, 10.0*BuildModel.TICK_PER_HOUR, false,10,"post", false);
		hireElectricityGenerator.setTask(hireElectricityGenerator.setTaskStats(1.0, 2.0*BuildModel.WORKINGHOURS));

		contactInsurer = new BehaviourSME (this, "contact insurer", 29.0, 2.0*BuildModel.TICK_PER_HOUR, false,11,"post", false);	
		contactInsurer.setTask(contactInsurer.setTaskStats(0.5, 3.0*BuildModel.WORKINGHOURS));

		contactLandlord = new BehaviourSME (this, "contact landlord", 30.0, 1.0*BuildModel.TICK_PER_HOUR, false,12,"post",false);
		contactLandlord.setTask(contactLandlord.setTaskStats(0.5, 16.0));

		catalogueDamage = new BehaviourSME(this, "catalogue damage", 30.0, 20.0*BuildModel.TICK_PER_HOUR,false,13 ,"post", true);
		catalogueDamage.setTask(catalogueDamage.setTaskStats(1.0, 5.0*BuildModel.WORKINGHOURS));

		waitInsurancePayment = new BehaviourSME(this, "wait for insurance payment", 1.0, 500.0*BuildModel.TICK_PER_HOUR, false,14,"post", false);
		waitInsurancePayment.setTask(catalogueDamage.setTaskStats(15.0*BuildModel.WORKINGHOURS, 90.0*BuildModel.WORKINGHOURS));

		cleanUpByEmployees = new BehaviourSME(this, "clean up by employees",30.0, 500.0*BuildModel.TICK_PER_HOUR, false,16,"post", true);
		cleanUpByEmployees.setTask(contactLandlord.setTaskStats(2.0, 6.0*BuildModel.WORKINGHOURS));

		workOnAboveFloors = new BehaviourSME (this, "move to upstairs", 30.0, 50.0*BuildModel.TICK_PER_HOUR, false,18,"post", true);
		workOnAboveFloors.setTask(workOnAboveFloors.setTaskStats(1.0, 5*BuildModel.WORKINGHOURS));

		directLandline = new BehaviourSME(this,"direct landline", 40.0, 2.0*BuildModel.TICK_PER_HOUR, false,19,"post", false);
		directLandline.setTask(directLandline.setTaskStats(0.5, 3.0*BuildModel.WORKINGHOURS));

		contactCustomers = new BehaviourSME(this, "contact customers", 30.0, 20.0*BuildModel.TICK_PER_HOUR, false,20,"post", false);
		contactCustomers.setTask(contactCustomers.setTaskStats(0.5, 16));

		contactSuppliers = new BehaviourSME(this, "contact suppliers", 30.0, 10.0*BuildModel.TICK_PER_HOUR, false,21,"post",false);
		contactSuppliers.setTask(contactSuppliers.setTaskStats(1.0, 16));

		contactContractors = new BehaviourSME(this, "contact contractors", 40.0, 4.0*BuildModel.TICK_PER_HOUR, false,23,"post", false);//empty in the design sheet
		contactContractors.setTask(contactContractors.setTaskStats(8.0, 40.0));

		waitContractors = new BehaviourSME(this, "wait for contractors", 1, 20.0*BuildModel.TICK_PER_HOUR, false,24,"post", false);	
		waitContractors.setTask(waitContractors.setTaskStats(8.0, 16.0));

		cleanUpByContractors = new BehaviourSME(this, "clean up by contractors", 30.0, 100.0*BuildModel.TICK_PER_HOUR, false,25,"post",false);
		cleanUpByContractors.setTask(cleanUpByContractors.setTaskStats(40.0, 80.0));

		sourceMoney = new BehaviourSME(this, "source money", 20.0, 100.0*BuildModel.TICK_PER_HOUR, false,26,"post", false);
		sourceMoney.setTask(sourceMoney.setTaskStats(1.0, 40.0));

		dryMachinary = new BehaviourSME(this, "dry machinary", 31.0, 100.0*BuildModel.TICK_PER_HOUR, false,28 ,"post", false);	
		dryMachinary.setTask(dryMachinary.setTaskStats(1.0, 10.0*BuildModel.WORKINGHOURS)); //Originally it is 90 days as maximum and can be shared

		moveStock= new BehaviourSME(this, "move stock", 30.0, 50.0*BuildModel.TICK_PER_HOUR, false,29,"post", true);	
		moveStock.setTask(moveStock.setTaskStats(1.0, 15*BuildModel.WORKINGHOURS));
			
		notAtWork = new BehaviourSME(this,"not at work", 100.0, numberVacancy*2.0*BuildModel.WORKINGHOURS*BuildModel.TICK_PER_HOUR, false,1000,"post",false);
		workWithAid= new BehaviourSME(this,"work with aid", 40.0, 500.0, false, 111, "post", false);
		requestAid= new BehaviourSME(this, "request aid", 40.0, 1.0, false,30, "post", false);
		
		behaviours.add(produce);
		behaviours.add(liftUpITEquipments);	
		behaviours.add(liftUpStock);

		if(this.getHasEngineers()){
			engineeringProtection = new BehaviourSME(this, "seal building", 40.0, 2.0*BuildModel.TICK_PER_HOUR, true, 3,"pre/during", true);
			engineeringProtection.setTask(engineeringProtection.setTaskStats(1.0, 4.0)*numberEmployees);
			behaviours.add(engineeringProtection);
		}
		//behaviours.add(waitToEvacuate);
		behaviours.add(evacuate);
		//	behaviours.add(notReturnToWork);

		behaviours.add(contactElectricians);
		//behaviours.add(waitForElectricians);
		behaviours.add(useElectricityGenerator);
		behaviours.add(hireElectricityGenerator);
		behaviours.add(restorePower);

		behaviours.add(catalogueDamage);		
		behaviours.add(contactInsurer);
		behaviours.add(sourceMoney);
		//behaviours.add(waitInsurancePayment);

		behaviours.add(directLandline);
		behaviours.add(contactSuppliers);
		behaviours.add(contactCustomers);

		behaviours.add(contactLandlord);

		behaviours.add(dryMachinary);
		behaviours.add(moveStock);				
		behaviours.add(workOnAboveFloors);		
		behaviours.add(cleanUpByEmployees);

		behaviours.add(contactContractors);
		//behaviours.add(waitContractors);
		behaviours.add(cleanUpByContractors);	

		behaviours.add(backToOperation);	
		behaviours.add(notAtWork);
		behaviours.add(workWithAid);
		behaviours.add(requestAid);
	
	}
	
	
}
